home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume10 / xlisp21 / part04 < prev    next >
Encoding:
Text File  |  1990-02-26  |  89.9 KB  |  4,152 lines

  1. Newsgroups: comp.sources.misc
  2. organization: Cognos Inc., Ottawa, Canada
  3. subject: v10i091: XLisP 2.1 sources 2/5
  4. From: garym@cognos.UUCP (Gary Murphy)
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 10, Issue 91
  8. Submitted-by: garym@cognos.UUCP (Gary Murphy)
  9. Archive-name: xlisp21/part04
  10.  
  11. #!/bin/sh
  12. # This is a shell archive, meaning:
  13. # 1. Remove everything above the #!/bin/sh line.
  14. # 2. Save the resulting text in a file.
  15. # 3. Execute the file with /bin/sh (not csh) to create the files:
  16. #    xlbfun.c
  17. #    xlcont.c
  18. #    xldbug.c
  19. #    xldmem.c
  20. #    xldmem.h
  21. #    xleval.c
  22. # This archive created: Sun Feb 18 07:45:24 1990
  23. # By:    Gary Murphy ()
  24. export PATH; PATH=/bin:$PATH
  25. echo shar: extracting "'xlbfun.c'" '(12891 characters)'
  26. if test -f 'xlbfun.c'
  27. then
  28.     echo shar: over-writing existing file "'xlbfun.c'"
  29. fi
  30. sed 's/^X//' << \SHAR_EOF > 'xlbfun.c'
  31. X/* xlbfun.c - xlisp basic built-in functions */
  32. X/*    Copyright (c) 1985, by David Michael Betz
  33. X    All Rights Reserved
  34. X    Permission is granted for unrestricted non-commercial use    */
  35. X
  36. X#include "xlisp.h"
  37. X
  38. X/* external variables */
  39. Xextern LVAL xlenv,xlfenv,xldenv,true;
  40. Xextern LVAL s_evalhook,s_applyhook;
  41. Xextern LVAL s_car,s_cdr,s_nth,s_get,s_svalue,s_splist,s_aref;
  42. Xextern LVAL s_lambda,s_macro;
  43. Xextern LVAL s_comma,s_comat;
  44. Xextern LVAL s_unbound;
  45. Xextern char gsprefix[];
  46. Xextern int gsnumber;
  47. X
  48. X/* external routines */
  49. Xextern LVAL xlxeval();
  50. X
  51. X/* forward declarations */
  52. XFORWARD LVAL bquote1();
  53. XFORWARD LVAL defun();
  54. XFORWARD LVAL makesymbol();
  55. X
  56. X/* xeval - the built-in function 'eval' */
  57. XLVAL xeval()
  58. X{
  59. X    LVAL expr;
  60. X
  61. X    /* get the expression to evaluate */
  62. X    expr = xlgetarg();
  63. X    xllastarg();
  64. X
  65. X    /* evaluate the expression */
  66. X    return (xleval(expr));
  67. X}
  68. X
  69. X/* xapply - the built-in function 'apply' */
  70. XLVAL xapply()
  71. X{
  72. X    LVAL fun,arglist;
  73. X
  74. X    /* get the function and argument list */
  75. X    fun = xlgetarg();
  76. X    arglist = xlgalist();
  77. X    xllastarg();
  78. X
  79. X    /* apply the function to the arguments */
  80. X    return (xlapply(pushargs(fun,arglist)));
  81. X}
  82. X
  83. X/* xfuncall - the built-in function 'funcall' */
  84. XLVAL xfuncall()
  85. X{
  86. X    LVAL *newfp;
  87. X    int argc;
  88. X    
  89. X    /* build a new argument stack frame */
  90. X    newfp = xlsp;
  91. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  92. X    pusharg(xlgetarg());
  93. X    pusharg(NIL); /* will be argc */
  94. X
  95. X    /* push each argument */
  96. X    for (argc = 0; moreargs(); ++argc)
  97. X    pusharg(nextarg());
  98. X
  99. X    /* establish the new stack frame */
  100. X    newfp[2] = cvfixnum((FIXTYPE)argc);
  101. X    xlfp = newfp;
  102. X
  103. X    /* apply the function to the arguments */
  104. X    return (xlapply(argc));
  105. X}
  106. X
  107. X/* xmacroexpand - expand a macro call repeatedly */
  108. XLVAL xmacroexpand()
  109. X{
  110. X    LVAL form;
  111. X    form = xlgetarg();
  112. X    xllastarg();
  113. X    return (xlexpandmacros(form));
  114. X}
  115. X
  116. X/* x1macroexpand - expand a macro call */
  117. XLVAL x1macroexpand()
  118. X{
  119. X    LVAL form,fun,args;
  120. X
  121. X    /* protect some pointers */
  122. X    xlstkcheck(2);
  123. X    xlsave(fun);
  124. X    xlsave(args);
  125. X
  126. X    /* get the form */
  127. X    form = xlgetarg();
  128. X    xllastarg();
  129. X
  130. X    /* expand until the form isn't a macro call */
  131. X    if (consp(form)) {
  132. X    fun = car(form);        /* get the macro name */
  133. X    args = cdr(form);        /* get the arguments */
  134. X    if (symbolp(fun) && fboundp(fun)) {
  135. X        fun = xlgetfunction(fun);    /* get the expansion function */
  136. X        macroexpand(fun,args,&form);
  137. X    }
  138. X    }
  139. X
  140. X    /* restore the stack and return the expansion */
  141. X    xlpopn(2);
  142. X    return (form);
  143. X}
  144. X
  145. X/* xatom - is this an atom? */
  146. XLVAL xatom()
  147. X{
  148. X    LVAL arg;
  149. X    arg = xlgetarg();
  150. X    xllastarg();
  151. X    return (atom(arg) ? true : NIL);
  152. X}
  153. X
  154. X/* xsymbolp - is this an symbol? */
  155. XLVAL xsymbolp()
  156. X{
  157. X    LVAL arg;
  158. X    arg = xlgetarg();
  159. X    xllastarg();
  160. X    return (arg == NIL || symbolp(arg) ? true : NIL);
  161. X}
  162. X
  163. X/* xnumberp - is this a number? */
  164. XLVAL xnumberp()
  165. X{
  166. X    LVAL arg;
  167. X    arg = xlgetarg();
  168. X    xllastarg();
  169. X    return (fixp(arg) || floatp(arg) ? true : NIL);
  170. X}
  171. X
  172. X/* xintegerp - is this an integer? */
  173. XLVAL xintegerp()
  174. X{
  175. X    LVAL arg;
  176. X    arg = xlgetarg();
  177. X    xllastarg();
  178. X    return (fixp(arg) ? true : NIL);
  179. X}
  180. X
  181. X/* xfloatp - is this a float? */
  182. XLVAL xfloatp()
  183. X{
  184. X    LVAL arg;
  185. X    arg = xlgetarg();
  186. X    xllastarg();
  187. X    return (floatp(arg) ? true : NIL);
  188. X}
  189. X
  190. X/* xcharp - is this a character? */
  191. XLVAL xcharp()
  192. X{
  193. X    LVAL arg;
  194. X    arg = xlgetarg();
  195. X    xllastarg();
  196. X    return (charp(arg) ? true : NIL);
  197. X}
  198. X
  199. X/* xstringp - is this a string? */
  200. XLVAL xstringp()
  201. X{
  202. X    LVAL arg;
  203. X    arg = xlgetarg();
  204. X    xllastarg();
  205. X    return (stringp(arg) ? true : NIL);
  206. X}
  207. X
  208. X/* xarrayp - is this an array? */
  209. XLVAL xarrayp()
  210. X{
  211. X    LVAL arg;
  212. X    arg = xlgetarg();
  213. X    xllastarg();
  214. X    return (vectorp(arg) ? true : NIL);
  215. X}
  216. X
  217. X/* xstreamp - is this a stream? */
  218. XLVAL xstreamp()
  219. X{
  220. X    LVAL arg;
  221. X    arg = xlgetarg();
  222. X    xllastarg();
  223. X    return (streamp(arg) || ustreamp(arg) ? true : NIL);
  224. X}
  225. X
  226. X/* xobjectp - is this an object? */
  227. XLVAL xobjectp()
  228. X{
  229. X    LVAL arg;
  230. X    arg = xlgetarg();
  231. X    xllastarg();
  232. X    return (objectp(arg) ? true : NIL);
  233. X}
  234. X
  235. X/* xboundp - is this a value bound to this symbol? */
  236. XLVAL xboundp()
  237. X{
  238. X    LVAL sym;
  239. X    sym = xlgasymbol();
  240. X    xllastarg();
  241. X    return (boundp(sym) ? true : NIL);
  242. X}
  243. X
  244. X/* xfboundp - is this a functional value bound to this symbol? */
  245. XLVAL xfboundp()
  246. X{
  247. X    LVAL sym;
  248. X    sym = xlgasymbol();
  249. X    xllastarg();
  250. X    return (fboundp(sym) ? true : NIL);
  251. X}
  252. X
  253. X/* xnull - is this null? */
  254. XLVAL xnull()
  255. X{
  256. X    LVAL arg;
  257. X    arg = xlgetarg();
  258. X    xllastarg();
  259. X    return (null(arg) ? true : NIL);
  260. X}
  261. X
  262. X/* xlistp - is this a list? */
  263. XLVAL xlistp()
  264. X{
  265. X    LVAL arg;
  266. X    arg = xlgetarg();
  267. X    xllastarg();
  268. X    return (listp(arg) ? true : NIL);
  269. X}
  270. X
  271. X/* xendp - is this the end of a list? */
  272. XLVAL xendp()
  273. X{
  274. X    LVAL arg;
  275. X    arg = xlgalist();
  276. X    xllastarg();
  277. X    return (null(arg) ? true : NIL);
  278. X}
  279. X
  280. X/* xconsp - is this a cons? */
  281. XLVAL xconsp()
  282. X{
  283. X    LVAL arg;
  284. X    arg = xlgetarg();
  285. X    xllastarg();
  286. X    return (consp(arg) ? true : NIL);
  287. X}
  288. X
  289. X/* xeq - are these equal? */
  290. XLVAL xeq()
  291. X{
  292. X    LVAL arg1,arg2;
  293. X
  294. X    /* get the two arguments */
  295. X    arg1 = xlgetarg();
  296. X    arg2 = xlgetarg();
  297. X    xllastarg();
  298. X
  299. X    /* compare the arguments */
  300. X    return (arg1 == arg2 ? true : NIL);
  301. X}
  302. X
  303. X/* xeql - are these equal? */
  304. XLVAL xeql()
  305. X{
  306. X    LVAL arg1,arg2;
  307. X
  308. X    /* get the two arguments */
  309. X    arg1 = xlgetarg();
  310. X    arg2 = xlgetarg();
  311. X    xllastarg();
  312. X
  313. X    /* compare the arguments */
  314. X    return (eql(arg1,arg2) ? true : NIL);
  315. X}
  316. X
  317. X/* xequal - are these equal? (recursive) */
  318. XLVAL xequal()
  319. X{
  320. X    LVAL arg1,arg2;
  321. X
  322. X    /* get the two arguments */
  323. X    arg1 = xlgetarg();
  324. X    arg2 = xlgetarg();
  325. X    xllastarg();
  326. X
  327. X    /* compare the arguments */
  328. X    return (equal(arg1,arg2) ? true : NIL);
  329. X}
  330. X
  331. X/* xset - built-in function set */
  332. XLVAL xset()
  333. X{
  334. X    LVAL sym,val;
  335. X
  336. X    /* get the symbol and new value */
  337. X    sym = xlgasymbol();
  338. X    val = xlgetarg();
  339. X    xllastarg();
  340. X
  341. X    /* assign the symbol the value of argument 2 and the return value */
  342. X    setvalue(sym,val);
  343. X
  344. X    /* return the result value */
  345. X    return (val);
  346. X}
  347. X
  348. X/* xgensym - generate a symbol */
  349. XLVAL xgensym()
  350. X{
  351. X    char sym[STRMAX+11]; /* enough space for prefix and number */
  352. X    LVAL x;
  353. X
  354. X    /* get the prefix or number */
  355. X    if (moreargs()) {
  356. X    x = xlgetarg();
  357. X    switch (ntype(x)) {
  358. X    case SYMBOL:
  359. X        x = getpname(x);
  360. X    case STRING:
  361. X        strncpy(gsprefix,getstring(x),STRMAX);
  362. X        gsprefix[STRMAX] = '\0';
  363. X        break;
  364. X    case FIXNUM:
  365. X        gsnumber = getfixnum(x);
  366. X        break;
  367. X    default:
  368. X        xlerror("bad argument type",x);
  369. X    }
  370. X    }
  371. X    xllastarg();
  372. X
  373. X    /* create the pname of the new symbol */
  374. X    sprintf(sym,"%s%d",gsprefix,gsnumber++);
  375. X
  376. X    /* make a symbol with this print name */
  377. X    return (xlmakesym(sym));
  378. X}
  379. X
  380. X/* xmakesymbol - make a new uninterned symbol */
  381. XLVAL xmakesymbol()
  382. X{
  383. X    return (makesymbol(FALSE));
  384. X}
  385. X
  386. X/* xintern - make a new interned symbol */
  387. XLVAL xintern()
  388. X{
  389. X    return (makesymbol(TRUE));
  390. X}
  391. X
  392. X/* makesymbol - make a new symbol */
  393. XLOCAL LVAL makesymbol(iflag)
  394. X  int iflag;
  395. X{
  396. X    LVAL pname;
  397. X
  398. X    /* get the print name of the symbol to intern */
  399. X    pname = xlgastring();
  400. X    xllastarg();
  401. X
  402. X    /* make the symbol */
  403. X    return (iflag ? xlenter(getstring(pname))
  404. X              : xlmakesym(getstring(pname)));
  405. X}
  406. X
  407. X/* xsymname - get the print name of a symbol */
  408. XLVAL xsymname()
  409. X{
  410. X    LVAL sym;
  411. X
  412. X    /* get the symbol */
  413. X    sym = xlgasymbol();
  414. X    xllastarg();
  415. X
  416. X    /* return the print name */
  417. X    return (getpname(sym));
  418. X}
  419. X
  420. X/* xsymvalue - get the value of a symbol */
  421. XLVAL xsymvalue()
  422. X{
  423. X    LVAL sym,val;
  424. X
  425. X    /* get the symbol */
  426. X    sym = xlgasymbol();
  427. X    xllastarg();
  428. X
  429. X    /* get the global value */
  430. X    while ((val = getvalue(sym)) == s_unbound)
  431. X    xlunbound(sym);
  432. X
  433. X    /* return its value */
  434. X    return (val);
  435. X}
  436. X
  437. X/* xsymfunction - get the functional value of a symbol */
  438. XLVAL xsymfunction()
  439. X{
  440. X    LVAL sym,val;
  441. X
  442. X    /* get the symbol */
  443. X    sym = xlgasymbol();
  444. X    xllastarg();
  445. X
  446. X    /* get the global value */
  447. X    while ((val = getfunction(sym)) == s_unbound)
  448. X    xlfunbound(sym);
  449. X
  450. X    /* return its value */
  451. X    return (val);
  452. X}
  453. X
  454. X/* xsymplist - get the property list of a symbol */
  455. XLVAL xsymplist()
  456. X{
  457. X    LVAL sym;
  458. X
  459. X    /* get the symbol */
  460. X    sym = xlgasymbol();
  461. X    xllastarg();
  462. X
  463. X    /* return the property list */
  464. X    return (getplist(sym));
  465. X}
  466. X
  467. X/* xget - get the value of a property */
  468. XLVAL xget()
  469. X{
  470. X    LVAL sym,prp;
  471. X
  472. X    /* get the symbol and property */
  473. X    sym = xlgasymbol();
  474. X    prp = xlgasymbol();
  475. X    xllastarg();
  476. X
  477. X    /* retrieve the property value */
  478. X    return (xlgetprop(sym,prp));
  479. X}
  480. X
  481. X/* xputprop - set the value of a property */
  482. XLVAL xputprop()
  483. X{
  484. X    LVAL sym,val,prp;
  485. X
  486. X    /* get the symbol and property */
  487. X    sym = xlgasymbol();
  488. X    val = xlgetarg();
  489. X    prp = xlgasymbol();
  490. X    xllastarg();
  491. X
  492. X    /* set the property value */
  493. X    xlputprop(sym,val,prp);
  494. X
  495. X    /* return the value */
  496. X    return (val);
  497. X}
  498. X
  499. X/* xremprop - remove a property value from a property list */
  500. XLVAL xremprop()
  501. X{
  502. X    LVAL sym,prp;
  503. X
  504. X    /* get the symbol and property */
  505. X    sym = xlgasymbol();
  506. X    prp = xlgasymbol();
  507. X    xllastarg();
  508. X
  509. X    /* remove the property */
  510. X    xlremprop(sym,prp);
  511. X
  512. X    /* return nil */
  513. X    return (NIL);
  514. X}
  515. X
  516. X/* xhash - compute the hash value of a string or symbol */
  517. XLVAL xhash()
  518. X{
  519. X    unsigned char *str;
  520. X    LVAL len,val;
  521. X    int n;
  522. X
  523. X    /* get the string and the table length */
  524. X    val = xlgetarg();
  525. X    len = xlgafixnum(); n = (int)getfixnum(len);
  526. X    xllastarg();
  527. X
  528. X    /* get the string */
  529. X    if (symbolp(val))
  530. X    str = getstring(getpname(val));
  531. X    else if (stringp(val))
  532. X    str = getstring(val);
  533. X    else
  534. X    xlerror("bad argument type",val);
  535. X
  536. X    /* return the hash index */
  537. X    return (cvfixnum((FIXTYPE)hash(str,n)));
  538. X}
  539. X
  540. X/* xaref - array reference function */
  541. XLVAL xaref()
  542. X{
  543. X    LVAL array,index;
  544. X    int i;
  545. X
  546. X    /* get the array and the index */
  547. X    array = xlgavector();
  548. X    index = xlgafixnum(); i = (int)getfixnum(index);
  549. X    xllastarg();
  550. X
  551. X    /* range check the index */
  552. X    if (i < 0 || i >= getsize(array))
  553. X    xlerror("array index out of bounds",index);
  554. X
  555. X    /* return the array element */
  556. X    return (getelement(array,i));
  557. X}
  558. X
  559. X/* xmkarray - make a new array */
  560. XLVAL xmkarray()
  561. X{
  562. X    LVAL size;
  563. X    int n;
  564. X
  565. X    /* get the size of the array */
  566. X    size = xlgafixnum() ; n = (int)getfixnum(size);
  567. X    xllastarg();
  568. X
  569. X    /* create the array */
  570. X    return (newvector(n));
  571. X}
  572. X
  573. X/* xvector - make a vector */
  574. XLVAL xvector()
  575. X{
  576. X    LVAL val;
  577. X    int i;
  578. X
  579. X    /* make the vector */
  580. X    val = newvector(xlargc);
  581. X
  582. X    /* store each argument */
  583. X    for (i = 0; moreargs(); ++i)
  584. X    setelement(val,i,nextarg());
  585. X    xllastarg();
  586. X
  587. X    /* return the vector */
  588. X    return (val);
  589. X}
  590. X
  591. X/* xerror - special form 'error' */
  592. XLVAL xerror()
  593. X{
  594. X    LVAL emsg,arg;
  595. X
  596. X    /* get the error message and the argument */
  597. X    emsg = xlgastring();
  598. X    arg = (moreargs() ? xlgetarg() : s_unbound);
  599. X    xllastarg();
  600. X
  601. X    /* signal the error */
  602. X    xlerror(getstring(emsg),arg);
  603. X}
  604. X
  605. X/* xcerror - special form 'cerror' */
  606. XLVAL xcerror()
  607. X{
  608. X    LVAL cmsg,emsg,arg;
  609. X
  610. X    /* get the correction message, the error message, and the argument */
  611. X    cmsg = xlgastring();
  612. X    emsg = xlgastring();
  613. X    arg = (moreargs() ? xlgetarg() : s_unbound);
  614. X    xllastarg();
  615. X
  616. X    /* signal the error */
  617. X    xlcerror(getstring(cmsg),getstring(emsg),arg);
  618. X
  619. X    /* return nil */
  620. X    return (NIL);
  621. X}
  622. X
  623. X/* xbreak - special form 'break' */
  624. XLVAL xbreak()
  625. X{
  626. X    LVAL emsg,arg;
  627. X
  628. X    /* get the error message */
  629. X    emsg = (moreargs() ? xlgastring() : NIL);
  630. X    arg = (moreargs() ? xlgetarg() : s_unbound);
  631. X    xllastarg();
  632. X
  633. X    /* enter the break loop */
  634. X    xlbreak((emsg ? getstring(emsg) : (unsigned char *)"**BREAK**"),arg);
  635. X
  636. X    /* return nil */
  637. X    return (NIL);
  638. X}
  639. X
  640. X/* xcleanup - special form 'clean-up' */
  641. XLVAL xcleanup()
  642. X{
  643. X    xllastarg();
  644. X    xlcleanup();
  645. X}
  646. X
  647. X/* xtoplevel - special form 'top-level' */
  648. XLVAL xtoplevel()
  649. X{
  650. X    xllastarg();
  651. X    xltoplevel();
  652. X}
  653. X
  654. X/* xcontinue - special form 'continue' */
  655. XLVAL xcontinue()
  656. X{
  657. X    xllastarg();
  658. X    xlcontinue();
  659. X}
  660. X
  661. X/* xevalhook - eval hook function */
  662. XLVAL xevalhook()
  663. X{
  664. X    LVAL expr,newehook,newahook,newenv,oldenv,oldfenv,olddenv,val;
  665. X
  666. X    /* protect some pointers */
  667. X    xlstkcheck(3);
  668. X    xlsave(oldenv);
  669. X    xlsave(oldfenv);
  670. X    xlsave(newenv);
  671. X
  672. X    /* get the expression, the new hook functions and the environment */
  673. X    expr = xlgetarg();
  674. X    newehook = xlgetarg();
  675. X    newahook = xlgetarg();
  676. X    newenv = (moreargs() ? xlgalist() : NIL);
  677. X    xllastarg();
  678. X
  679. X    /* bind *evalhook* and *applyhook* to the hook functions */
  680. X    olddenv = xldenv;
  681. X    xldbind(s_evalhook,newehook);
  682. X    xldbind(s_applyhook,newahook);
  683. X
  684. X    /* establish the environment for the hook function */
  685. X    if (newenv) {
  686. X    oldenv = xlenv;
  687. X    oldfenv = xlfenv;
  688. X    xlenv = car(newenv);
  689. X    xlfenv = cdr(newenv);
  690. X    }
  691. X
  692. X    /* evaluate the expression (bypassing *evalhook*) */
  693. X    val = xlxeval(expr);
  694. X
  695. X    /* restore the old environment */
  696. X    xlunbind(olddenv);
  697. X    if (newenv) {
  698. X    xlenv = oldenv;
  699. X    xlfenv = oldfenv;
  700. X    }
  701. X
  702. X    /* restore the stack */
  703. X    xlpopn(3);
  704. X
  705. X    /* return the result */
  706. X    return (val);
  707. X}
  708. X
  709. SHAR_EOF
  710. if test 12891 -ne "`wc -c 'xlbfun.c'`"
  711. then
  712.     echo shar: error transmitting "'xlbfun.c'" '(should have been 12891 characters)'
  713. fi
  714. echo shar: extracting "'xlcont.c'" '(28157 characters)'
  715. if test -f 'xlcont.c'
  716. then
  717.     echo shar: over-writing existing file "'xlcont.c'"
  718. fi
  719. sed 's/^X//' << \SHAR_EOF > 'xlcont.c'
  720. X/* xlcont - xlisp special forms */
  721. X/*    Copyright (c) 1985, by David Michael Betz
  722. X    All Rights Reserved
  723. X    Permission is granted for unrestricted non-commercial use    */
  724. X
  725. X#include "xlisp.h"
  726. X
  727. X/* external variables */
  728. Xextern LVAL xlenv,xlfenv,xldenv,xlvalue;
  729. Xextern LVAL s_setf,s_car,s_cdr,s_nth,s_aref,s_get;
  730. Xextern LVAL s_svalue,s_sfunction,s_splist;
  731. Xextern LVAL s_lambda,s_macro;
  732. Xextern LVAL s_comma,s_comat;
  733. Xextern LVAL s_unbound;
  734. Xextern LVAL true;
  735. X
  736. X/* external routines */
  737. Xextern LVAL makearglist();
  738. X
  739. X/* forward declarations */
  740. XFORWARD LVAL bquote1();
  741. XFORWARD LVAL let();
  742. XFORWARD LVAL flet();
  743. XFORWARD LVAL prog();
  744. XFORWARD LVAL progx();
  745. XFORWARD LVAL doloop();
  746. XFORWARD LVAL evarg();
  747. XFORWARD LVAL match();
  748. XFORWARD LVAL evmatch();
  749. X
  750. X/* dummy node type for a list */
  751. X#define LIST    -1
  752. X
  753. X/* xquote - special form 'quote' */
  754. XLVAL xquote()
  755. X{
  756. X    LVAL val;
  757. X    val = xlgetarg();
  758. X    xllastarg();
  759. X    return (val);
  760. X}
  761. X
  762. X/* xfunction - special form 'function' */
  763. XLVAL xfunction()
  764. X{
  765. X    LVAL val;
  766. X
  767. X    /* get the argument */
  768. X    val = xlgetarg();
  769. X    xllastarg();
  770. X
  771. X    /* create a closure for lambda expressions */
  772. X    if (consp(val) && car(val) == s_lambda && consp(cdr(val)))
  773. X    val = xlclose(NIL,s_lambda,car(cdr(val)),cdr(cdr(val)),xlenv,xlfenv);
  774. X
  775. X    /* otherwise, get the value of a symbol */
  776. X    else if (symbolp(val))
  777. X    val = xlgetfunction(val);
  778. X
  779. X    /* otherwise, its an error */
  780. X    else
  781. X    xlerror("not a function",val);
  782. X
  783. X    /* return the function */
  784. X    return (val);
  785. X}
  786. X
  787. X/* xbquote - back quote special form */
  788. XLVAL xbquote()
  789. X{
  790. X    LVAL expr;
  791. X
  792. X    /* get the expression */
  793. X    expr = xlgetarg();
  794. X    xllastarg();
  795. X
  796. X    /* fill in the template */
  797. X    return (bquote1(expr));
  798. X}
  799. X
  800. X/* bquote1 - back quote helper function */
  801. XLOCAL LVAL bquote1(expr)
  802. X  LVAL expr;
  803. X{
  804. X    LVAL val,list,last,new;
  805. X
  806. X    /* handle atoms */
  807. X    if (atom(expr))
  808. X    val = expr;
  809. X
  810. X    /* handle (comma <expr>) */
  811. X    else if (car(expr) == s_comma) {
  812. X    if (atom(cdr(expr)))
  813. X        xlfail("bad comma expression");
  814. X    val = xleval(car(cdr(expr)));
  815. X    }
  816. X
  817. X    /* handle ((comma-at <expr>) ... ) */
  818. X    else if (consp(car(expr)) && car(car(expr)) == s_comat) {
  819. X    xlstkcheck(2);
  820. X    xlsave(list);
  821. X    xlsave(val);
  822. X    if (atom(cdr(car(expr))))
  823. X        xlfail("bad comma-at expression");
  824. X    list = xleval(car(cdr(car(expr))));
  825. X    for (last = NIL; consp(list); list = cdr(list)) {
  826. X        new = consa(car(list));
  827. X        if (last)
  828. X        rplacd(last,new);
  829. X        else
  830. X        val = new;
  831. X        last = new;
  832. X    }
  833. X    if (last)
  834. X        rplacd(last,bquote1(cdr(expr)));
  835. X    else
  836. X        val = bquote1(cdr(expr));
  837. X    xlpopn(2);
  838. X    }
  839. X
  840. X    /* handle any other list */
  841. X    else {
  842. X    xlsave1(val);
  843. X    val = consa(NIL);
  844. X    rplaca(val,bquote1(car(expr)));
  845. X    rplacd(val,bquote1(cdr(expr)));
  846. X    xlpop();
  847. X    }
  848. X
  849. X    /* return the result */
  850. X    return (val);
  851. X}
  852. X
  853. X/* xlambda - special form 'lambda' */
  854. XLVAL xlambda()
  855. X{
  856. X    LVAL fargs,arglist,val;
  857. X
  858. X    /* get the formal argument list and function body */
  859. X    xlsave1(arglist);
  860. X    fargs = xlgalist();
  861. X    arglist = makearglist(xlargc,xlargv);
  862. X
  863. X    /* create a new function definition */
  864. X    val = xlclose(NIL,s_lambda,fargs,arglist,xlenv,xlfenv);
  865. X
  866. X    /* restore the stack and return the closure */
  867. X    xlpop();
  868. X    return (val);
  869. X}
  870. X
  871. X/* xgetlambda - get the lambda expression associated with a closure */
  872. XLVAL xgetlambda()
  873. X{
  874. X    LVAL closure;
  875. X    closure = xlgaclosure();
  876. X    return (cons(gettype(closure),
  877. X                 cons(getlambda(closure),getbody(closure))));
  878. X}
  879. X
  880. X/* xsetq - special form 'setq' */
  881. XLVAL xsetq()
  882. X{
  883. X    LVAL sym,val;
  884. X
  885. X    /* handle each pair of arguments */
  886. X    for (val = NIL; moreargs(); ) {
  887. X    sym = xlgasymbol();
  888. X    val = xleval(nextarg());
  889. X    xlsetvalue(sym,val);
  890. X    }
  891. X
  892. X    /* return the result value */
  893. X    return (val);
  894. X}
  895. X
  896. X/* xpsetq - special form 'psetq' */
  897. XLVAL xpsetq()
  898. X{
  899. X    LVAL plist,sym,val;
  900. X
  901. X    /* protect some pointers */
  902. X    xlsave1(plist);
  903. X
  904. X    /* handle each pair of arguments */
  905. X    for (val = NIL; moreargs(); ) {
  906. X    sym = xlgasymbol();
  907. X    val = xleval(nextarg());
  908. X    plist = cons(cons(sym,val),plist);
  909. X    }
  910. X
  911. X    /* do parallel sets */
  912. X    for (; plist; plist = cdr(plist))
  913. X    xlsetvalue(car(car(plist)),cdr(car(plist)));
  914. X
  915. X    /* restore the stack */
  916. X    xlpop();
  917. X
  918. X    /* return the result value */
  919. X    return (val);
  920. X}
  921. X
  922. X/* xsetf - special form 'setf' */
  923. XLVAL xsetf()
  924. X{
  925. X    LVAL place,value;
  926. X
  927. X    /* protect some pointers */
  928. X    xlsave1(value);
  929. X
  930. X    /* handle each pair of arguments */
  931. X    while (moreargs()) {
  932. X
  933. X    /* get place and value */
  934. X    place = xlgetarg();
  935. X    value = xleval(nextarg());
  936. X
  937. X    /* expand macros in the place form */
  938. X    if (consp(place))
  939. X        place = xlexpandmacros(place);
  940. X    
  941. X    /* check the place form */
  942. X    if (symbolp(place))
  943. X        xlsetvalue(place,value);
  944. X    else if (consp(place))
  945. X        placeform(place,value);
  946. X    else
  947. X        xlfail("bad place form");
  948. X    }
  949. X
  950. X    /* restore the stack */
  951. X    xlpop();
  952. X
  953. X    /* return the value */
  954. X    return (value);
  955. X}
  956. X
  957. X/* placeform - handle a place form other than a symbol */
  958. XLOCAL placeform(place,value)
  959. X  LVAL place,value;
  960. X{
  961. X    LVAL fun,arg1,arg2;
  962. X    int i;
  963. X
  964. X    /* check the function name */
  965. X    if ((fun = match(SYMBOL,&place)) == s_get) {
  966. X    xlstkcheck(2);
  967. X    xlsave(arg1);
  968. X    xlsave(arg2);
  969. X    arg1 = evmatch(SYMBOL,&place);
  970. X    arg2 = evmatch(SYMBOL,&place);
  971. X    if (place) toomany(place);
  972. X    xlputprop(arg1,value,arg2);
  973. X    xlpopn(2);
  974. X    }
  975. X    else if (fun == s_svalue) {
  976. X    arg1 = evmatch(SYMBOL,&place);
  977. X    if (place) toomany(place);
  978. X    setvalue(arg1,value);
  979. X    }
  980. X    else if (fun == s_sfunction) {
  981. X    arg1 = evmatch(SYMBOL,&place);
  982. X    if (place) toomany(place);
  983. X    setfunction(arg1,value);
  984. X    }
  985. X    else if (fun == s_splist) {
  986. X    arg1 = evmatch(SYMBOL,&place);
  987. X    if (place) toomany(place);
  988. X    setplist(arg1,value);
  989. X    }
  990. X    else if (fun == s_car) {
  991. X    arg1 = evmatch(CONS,&place);
  992. X    if (place) toomany(place);
  993. X    rplaca(arg1,value);
  994. X    }
  995. X    else if (fun == s_cdr) {
  996. X    arg1 = evmatch(CONS,&place);
  997. X    if (place) toomany(place);
  998. X    rplacd(arg1,value);
  999. X    }
  1000. X    else if (fun == s_nth) {
  1001. X    xlsave1(arg1);
  1002. X    arg1 = evmatch(FIXNUM,&place);
  1003. X    arg2 = evmatch(LIST,&place);
  1004. X    if (place) toomany(place);
  1005. X    for (i = (int)getfixnum(arg1); i > 0 && consp(arg2); --i)
  1006. X        arg2 = cdr(arg2);
  1007. X    if (consp(arg2))
  1008. X        rplaca(arg2,value);
  1009. X    xlpop();
  1010. X    }
  1011. X    else if (fun == s_aref) {
  1012. X    xlsave1(arg1);
  1013. X    arg1 = evmatch(VECTOR,&place);
  1014. X    arg2 = evmatch(FIXNUM,&place); i = (int)getfixnum(arg2);
  1015. X    if (place) toomany(place);
  1016. X    if (i < 0 || i >= getsize(arg1))
  1017. X        xlerror("index out of range",arg2);
  1018. X    setelement(arg1,i,value);
  1019. X    xlpop();
  1020. X    }
  1021. X    else if (fun = xlgetprop(fun,s_setf))
  1022. X    setffunction(fun,place,value);
  1023. X    else
  1024. X    xlfail("bad place form");
  1025. X}
  1026. X
  1027. X/* setffunction - call a user defined setf function */
  1028. XLOCAL setffunction(fun,place,value)
  1029. X  LVAL fun,place,value;
  1030. X{
  1031. X    LVAL *newfp;
  1032. X    int argc;
  1033. X
  1034. X    /* create the new call frame */
  1035. X    newfp = xlsp;
  1036. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  1037. X    pusharg(fun);
  1038. X    pusharg(NIL);
  1039. X
  1040. X    /* push the values of all of the place expressions and the new value */
  1041. X    for (argc = 1; consp(place); place = cdr(place), ++argc)
  1042. X    pusharg(xleval(car(place)));
  1043. X    pusharg(value);
  1044. X
  1045. X    /* insert the argument count and establish the call frame */
  1046. X    newfp[2] = cvfixnum((FIXTYPE)argc);
  1047. X    xlfp = newfp;
  1048. X
  1049. X    /* apply the function */
  1050. X    xlapply(argc);
  1051. X}
  1052. X               
  1053. X/* xdefun - special form 'defun' */
  1054. XLVAL xdefun()
  1055. X{
  1056. X    LVAL sym,fargs,arglist;
  1057. X
  1058. X    /* get the function symbol and formal argument list */
  1059. X    xlsave1(arglist);
  1060. X    sym = xlgasymbol();
  1061. X    fargs = xlgalist();
  1062. X    arglist = makearglist(xlargc,xlargv);
  1063. X
  1064. X    /* make the symbol point to a new function definition */
  1065. X    xlsetfunction(sym,xlclose(sym,s_lambda,fargs,arglist,xlenv,xlfenv));
  1066. X
  1067. X    /* restore the stack and return the function symbol */
  1068. X    xlpop();
  1069. X    return (sym);
  1070. X}
  1071. X
  1072. X/* xdefmacro - special form 'defmacro' */
  1073. XLVAL xdefmacro()
  1074. X{
  1075. X    LVAL sym,fargs,arglist;
  1076. X
  1077. X    /* get the function symbol and formal argument list */
  1078. X    xlsave1(arglist);
  1079. X    sym = xlgasymbol();
  1080. X    fargs = xlgalist();
  1081. X    arglist = makearglist(xlargc,xlargv);
  1082. X
  1083. X    /* make the symbol point to a new function definition */
  1084. X    xlsetfunction(sym,xlclose(sym,s_macro,fargs,arglist,NIL,NIL));
  1085. X
  1086. X    /* restore the stack and return the function symbol */
  1087. X    xlpop();
  1088. X    return (sym);
  1089. X}
  1090. X
  1091. X/* xcond - special form 'cond' */
  1092. XLVAL xcond()
  1093. X{
  1094. X    LVAL list,val;
  1095. X
  1096. X    /* find a predicate that is true */
  1097. X    for (val = NIL; moreargs(); ) {
  1098. X
  1099. X    /* get the next conditional */
  1100. X    list = nextarg();
  1101. X
  1102. X    /* evaluate the predicate part */
  1103. X    if (consp(list) && (val = xleval(car(list)))) {
  1104. X
  1105. X        /* evaluate each expression */
  1106. X        for (list = cdr(list); consp(list); list = cdr(list))
  1107. X        val = xleval(car(list));
  1108. X
  1109. X        /* exit the loop */
  1110. X        break;
  1111. X    }
  1112. X    }
  1113. X
  1114. X    /* return the value */
  1115. X    return (val);
  1116. X}
  1117. X
  1118. X/* xwhen - special form 'when' */
  1119. XLVAL xwhen()
  1120. X{
  1121. X    LVAL val;
  1122. X
  1123. X    /* check the test expression */
  1124. X    if (val = xleval(xlgetarg()))
  1125. X    while (moreargs())
  1126. X        val = xleval(nextarg());
  1127. X
  1128. X    /* return the value */
  1129. X    return (val);
  1130. X}
  1131. X
  1132. X/* xunless - special form 'unless' */
  1133. XLVAL xunless()
  1134. X{
  1135. X    LVAL val=NIL;
  1136. X
  1137. X    /* check the test expression */
  1138. X    if (xleval(xlgetarg()) == NIL)
  1139. X    while (moreargs())
  1140. X        val = xleval(nextarg());
  1141. X
  1142. X    /* return the value */
  1143. X    return (val);
  1144. X}
  1145. X
  1146. X/* xcase - special form 'case' */
  1147. XLVAL xcase()
  1148. X{
  1149. X    LVAL key,list,cases,val;
  1150. X
  1151. X    /* protect some pointers */
  1152. X    xlsave1(key);
  1153. X
  1154. X    /* get the key expression */
  1155. X    key = xleval(nextarg());
  1156. X
  1157. X    /* find a case that matches */
  1158. X    for (val = NIL; moreargs(); ) {
  1159. X
  1160. X    /* get the next case clause */
  1161. X    list = nextarg();
  1162. X
  1163. X    /* make sure this is a valid clause */
  1164. X    if (consp(list)) {
  1165. X
  1166. X        /* compare the key list against the key */
  1167. X        if ((cases = car(list)) == true ||
  1168. X                (listp(cases) && keypresent(key,cases)) ||
  1169. X                eql(key,cases)) {
  1170. X
  1171. X        /* evaluate each expression */
  1172. X        for (list = cdr(list); consp(list); list = cdr(list))
  1173. X            val = xleval(car(list));
  1174. X
  1175. X        /* exit the loop */
  1176. X        break;
  1177. X        }
  1178. X    }
  1179. X    else
  1180. X        xlerror("bad case clause",list);
  1181. X    }
  1182. X
  1183. X    /* restore the stack */
  1184. X    xlpop();
  1185. X
  1186. X    /* return the value */
  1187. X    return (val);
  1188. X}
  1189. X
  1190. X/* keypresent - check for the presence of a key in a list */
  1191. XLOCAL int keypresent(key,list)
  1192. X  LVAL key,list;
  1193. X{
  1194. X    for (; consp(list); list = cdr(list))
  1195. X    if (eql(car(list),key))
  1196. X        return (TRUE);
  1197. X    return (FALSE);
  1198. X}
  1199. X
  1200. X/* xand - special form 'and' */
  1201. XLVAL xand()
  1202. X{
  1203. X    LVAL val;
  1204. X
  1205. X    /* evaluate each argument */
  1206. X    for (val = true; moreargs(); )
  1207. X    if ((val = xleval(nextarg())) == NIL)
  1208. X        break;
  1209. X
  1210. X    /* return the result value */
  1211. X    return (val);
  1212. X}
  1213. X
  1214. X/* xor - special form 'or' */
  1215. XLVAL xor()
  1216. X{
  1217. X    LVAL val;
  1218. X
  1219. X    /* evaluate each argument */
  1220. X    for (val = NIL; moreargs(); )
  1221. X    if ((val = xleval(nextarg())))
  1222. X        break;
  1223. X
  1224. X    /* return the result value */
  1225. X    return (val);
  1226. X}
  1227. X
  1228. X/* xif - special form 'if' */
  1229. XLVAL xif()
  1230. X{
  1231. X    LVAL testexpr,thenexpr,elseexpr;
  1232. X
  1233. X    /* get the test expression, then clause and else clause */
  1234. X    testexpr = xlgetarg();
  1235. X    thenexpr = xlgetarg();
  1236. X    elseexpr = (moreargs() ? xlgetarg() : NIL);
  1237. X    xllastarg();
  1238. X
  1239. X    /* evaluate the appropriate clause */
  1240. X    return (xleval(xleval(testexpr) ? thenexpr : elseexpr));
  1241. X}
  1242. X
  1243. X/* xlet - special form 'let' */
  1244. XLVAL xlet()
  1245. X{
  1246. X    return (let(TRUE));
  1247. X}
  1248. X
  1249. X/* xletstar - special form 'let*' */
  1250. XLVAL xletstar()
  1251. X{
  1252. X    return (let(FALSE));
  1253. X}
  1254. X
  1255. X/* let - common let routine */
  1256. XLOCAL LVAL let(pflag)
  1257. X  int pflag;
  1258. X{
  1259. X    LVAL newenv,val;
  1260. X
  1261. X    /* protect some pointers */
  1262. X    xlsave1(newenv);
  1263. X
  1264. X    /* create a new environment frame */
  1265. X    newenv = xlframe(xlenv);
  1266. X
  1267. X    /* get the list of bindings and bind the symbols */
  1268. X    if (!pflag) xlenv = newenv;
  1269. X    dobindings(xlgalist(),newenv);
  1270. X    if (pflag) xlenv = newenv;
  1271. X
  1272. X    /* execute the code */
  1273. X    for (val = NIL; moreargs(); )
  1274. X    val = xleval(nextarg());
  1275. X
  1276. X    /* unbind the arguments */
  1277. X    xlenv = cdr(xlenv);
  1278. X
  1279. X    /* restore the stack */
  1280. X    xlpop();
  1281. X
  1282. X    /* return the result */
  1283. X    return (val);
  1284. X}
  1285. X
  1286. X/* xflet - built-in function 'flet' */
  1287. XLVAL xflet()
  1288. X{
  1289. X    return (flet(s_lambda,TRUE));
  1290. X}
  1291. X
  1292. X/* xlabels - built-in function 'labels' */
  1293. XLVAL xlabels()
  1294. X{
  1295. X    return (flet(s_lambda,FALSE));
  1296. X}
  1297. X
  1298. X/* xmacrolet - built-in function 'macrolet' */
  1299. XLVAL xmacrolet()
  1300. X{
  1301. X    return (flet(s_macro,TRUE));
  1302. X}
  1303. X
  1304. X/* flet - common flet/labels/macrolet routine */
  1305. XLOCAL LVAL flet(type,letflag)
  1306. X  LVAL type; int letflag;
  1307. X{
  1308. X    LVAL list,bnd,sym,fargs,val;
  1309. X
  1310. X    /* create a new environment frame */
  1311. X    xlfenv = xlframe(xlfenv);
  1312. X
  1313. X    /* bind each symbol in the list of bindings */
  1314. X    for (list = xlgalist(); consp(list); list = cdr(list)) {
  1315. X
  1316. X    /* get the next binding */
  1317. X    bnd = car(list);
  1318. X
  1319. X    /* get the symbol and the function definition */
  1320. X    sym = match(SYMBOL,&bnd);
  1321. X    fargs = match(LIST,&bnd);
  1322. X    val = xlclose(sym,type,fargs,bnd,xlenv,(letflag?cdr(xlfenv):xlfenv));
  1323. X
  1324. X    /* bind the value to the symbol */
  1325. X    xlfbind(sym,val);
  1326. X    }
  1327. X
  1328. X    /* execute the code */
  1329. X    for (val = NIL; moreargs(); )
  1330. X    val = xleval(nextarg());
  1331. X
  1332. X    /* unbind the arguments */
  1333. X    xlfenv = cdr(xlfenv);
  1334. X
  1335. X    /* return the result */
  1336. X    return (val);
  1337. X}
  1338. X
  1339. X/* xprog - special form 'prog' */
  1340. XLVAL xprog()
  1341. X{
  1342. X    return (prog(TRUE));
  1343. X}
  1344. X
  1345. X/* xprogstar - special form 'prog*' */
  1346. XLVAL xprogstar()
  1347. X{
  1348. X    return (prog(FALSE));
  1349. X}
  1350. X
  1351. X/* prog - common prog routine */
  1352. XLOCAL LVAL prog(pflag)
  1353. X  int pflag;
  1354. X{
  1355. X    LVAL newenv,val;
  1356. X    CONTEXT cntxt;
  1357. X
  1358. X    /* protect some pointers */
  1359. X    xlsave1(newenv);
  1360. X
  1361. X    /* create a new environment frame */
  1362. X    newenv = xlframe(xlenv);
  1363. X
  1364. X    /* establish a new execution context */
  1365. X    xlbegin(&cntxt,CF_RETURN,NIL);
  1366. X    if (setjmp(cntxt.c_jmpbuf))
  1367. X    val = xlvalue;
  1368. X    else {
  1369. X
  1370. X    /* get the list of bindings and bind the symbols */
  1371. X    if (!pflag) xlenv = newenv;
  1372. X    dobindings(xlgalist(),newenv);
  1373. X    if (pflag) xlenv = newenv;
  1374. X
  1375. X    /* execute the code */
  1376. X    tagbody();
  1377. X    val = NIL;
  1378. X
  1379. X    /* unbind the arguments */
  1380. X    xlenv = cdr(xlenv);
  1381. X    }
  1382. X    xlend(&cntxt);
  1383. X
  1384. X    /* restore the stack */
  1385. X    xlpop();
  1386. X
  1387. X    /* return the result */
  1388. X    return (val);
  1389. X}
  1390. X
  1391. X/* xgo - special form 'go' */
  1392. XLVAL xgo()
  1393. X{
  1394. X    LVAL label;
  1395. X
  1396. X    /* get the target label */
  1397. X    label = xlgetarg();
  1398. X    xllastarg();
  1399. X
  1400. X    /* transfer to the label */
  1401. X    xlgo(label);
  1402. X}
  1403. X
  1404. X/* xreturn - special form 'return' */
  1405. XLVAL xreturn()
  1406. X{
  1407. X    LVAL val;
  1408. X
  1409. X    /* get the return value */
  1410. X    val = (moreargs() ? xleval(nextarg()) : NIL);
  1411. X    xllastarg();
  1412. X
  1413. X    /* return from the inner most block */
  1414. X    xlreturn(NIL,val);
  1415. X}
  1416. X
  1417. X/* xrtnfrom - special form 'return-from' */
  1418. XLVAL xrtnfrom()
  1419. X{
  1420. X    LVAL name,val;
  1421. X
  1422. X    /* get the return value */
  1423. X    name = xlgasymbol();
  1424. X    val = (moreargs() ? xleval(nextarg()) : NIL);
  1425. X    xllastarg();
  1426. X
  1427. X    /* return from the inner most block */
  1428. X    xlreturn(name,val);
  1429. X}
  1430. X
  1431. X/* xprog1 - special form 'prog1' */
  1432. XLVAL xprog1()
  1433. X{
  1434. X    return (progx(1));
  1435. X}
  1436. X
  1437. X/* xprog2 - special form 'prog2' */
  1438. XLVAL xprog2()
  1439. X{
  1440. X    return (progx(2));
  1441. X}
  1442. X
  1443. X/* progx - common progx code */
  1444. XLOCAL LVAL progx(n)
  1445. X  int n;
  1446. X{
  1447. X    LVAL val;
  1448. X
  1449. X    /* protect some pointers */
  1450. X    xlsave1(val);
  1451. X
  1452. X    /* evaluate the first n expressions */
  1453. X    while (moreargs() && --n >= 0)
  1454. X    val = xleval(nextarg());
  1455. X
  1456. X    /* evaluate each remaining argument */
  1457. X    while (moreargs())
  1458. X    xleval(nextarg());
  1459. X
  1460. X    /* restore the stack */
  1461. X    xlpop();
  1462. X
  1463. X    /* return the last test expression value */
  1464. X    return (val);
  1465. X}
  1466. X
  1467. X/* xprogn - special form 'progn' */
  1468. XLVAL xprogn()
  1469. X{
  1470. X    LVAL val;
  1471. X
  1472. X    /* evaluate each expression */
  1473. X    for (val = NIL; moreargs(); )
  1474. X    val = xleval(nextarg());
  1475. X
  1476. X    /* return the last test expression value */
  1477. X    return (val);
  1478. X}
  1479. X
  1480. X/* xprogv - special form 'progv' */
  1481. XLVAL xprogv()
  1482. X{
  1483. X    LVAL olddenv,vars,vals,val;
  1484. X
  1485. X    /* protect some pointers */
  1486. X    xlstkcheck(2);
  1487. X    xlsave(vars);
  1488. X    xlsave(vals);
  1489. X
  1490. X    /* get the list of variables and the list of values */
  1491. X    vars = xlgalist(); vars = xleval(vars);
  1492. X    vals = xlgalist(); vals = xleval(vals);
  1493. X
  1494. X    /* bind the values to the variables */
  1495. X    for (olddenv = xldenv; consp(vars); vars = cdr(vars)) {
  1496. X    if (!symbolp(car(vars)))
  1497. X        xlerror("expecting a symbol",car(vars));
  1498. X    if (consp(vals)) {
  1499. X        xldbind(car(vars),car(vals));
  1500. X        vals = cdr(vals);
  1501. X    }
  1502. X    else
  1503. X        xldbind(car(vars),s_unbound);
  1504. X    }
  1505. X
  1506. X    /* evaluate each expression */
  1507. X    for (val = NIL; moreargs(); )
  1508. X    val = xleval(nextarg());
  1509. X
  1510. X    /* restore the previous environment and the stack */
  1511. X    xlunbind(olddenv);
  1512. X    xlpopn(2);
  1513. X
  1514. X    /* return the last test expression value */
  1515. X    return (val);
  1516. X}
  1517. X
  1518. X/* xloop - special form 'loop' */
  1519. XLVAL xloop()
  1520. X{
  1521. X    LVAL *argv,arg,val;
  1522. X    CONTEXT cntxt;
  1523. X    int argc;
  1524. X
  1525. X    /* protect some pointers */
  1526. X    xlsave1(arg);
  1527. X
  1528. X    /* establish a new execution context */
  1529. X    xlbegin(&cntxt,CF_RETURN,NIL);
  1530. X    if (setjmp(cntxt.c_jmpbuf))
  1531. X    val = xlvalue;
  1532. X    else
  1533. X    for (argv = xlargv, argc = xlargc; ; xlargv = argv, xlargc = argc)
  1534. X        while (moreargs()) {
  1535. X        arg = nextarg();
  1536. X        if (consp(arg))
  1537. X            xleval(arg);
  1538. X        }
  1539. X    xlend(&cntxt);
  1540. X
  1541. X    /* restore the stack */
  1542. X    xlpop();
  1543. X
  1544. X    /* return the result */
  1545. X    return (val);
  1546. X}
  1547. X
  1548. X/* xdo - special form 'do' */
  1549. XLVAL xdo()
  1550. X{
  1551. X    return (doloop(TRUE));
  1552. X}
  1553. X
  1554. X/* xdostar - special form 'do*' */
  1555. XLVAL xdostar()
  1556. X{
  1557. X    return (doloop(FALSE));
  1558. X}
  1559. X
  1560. X/* doloop - common do routine */
  1561. XLOCAL LVAL doloop(pflag)
  1562. X  int pflag;
  1563. X{
  1564. X    LVAL newenv,*argv,blist,clist,test,val;
  1565. X    CONTEXT cntxt;
  1566. X    int argc;
  1567. X
  1568. X    /* protect some pointers */
  1569. X    xlsave1(newenv);
  1570. X
  1571. X    /* get the list of bindings, the exit test and the result forms */
  1572. X    blist = xlgalist();
  1573. X    clist = xlgalist();
  1574. X    test = (consp(clist) ? car(clist) : NIL);
  1575. X    argv = xlargv;
  1576. X    argc = xlargc;
  1577. X
  1578. X    /* create a new environment frame */
  1579. X    newenv = xlframe(xlenv);
  1580. X
  1581. X    /* establish a new execution context */
  1582. X    xlbegin(&cntxt,CF_RETURN,NIL);
  1583. X    if (setjmp(cntxt.c_jmpbuf))
  1584. X    val = xlvalue;
  1585. X    else {
  1586. X
  1587. X    /* bind the symbols */
  1588. X    if (!pflag) xlenv = newenv;
  1589. X    dobindings(blist,newenv);
  1590. X    if (pflag) xlenv = newenv;
  1591. X
  1592. X    /* execute the loop as long as the test is false */
  1593. X    for (val = NIL; xleval(test) == NIL; doupdates(blist,pflag)) {
  1594. X        xlargv = argv;
  1595. X        xlargc = argc;
  1596. X        tagbody();
  1597. X    }
  1598. X
  1599. X    /* evaluate the result expression */
  1600. X    if (consp(clist))
  1601. X        for (clist = cdr(clist); consp(clist); clist = cdr(clist))
  1602. X        val = xleval(car(clist));
  1603. X
  1604. X    /* unbind the arguments */
  1605. X    xlenv = cdr(xlenv);
  1606. X    }
  1607. X    xlend(&cntxt);
  1608. X
  1609. X    /* restore the stack */
  1610. X    xlpop();
  1611. X
  1612. X    /* return the result */
  1613. X    return (val);
  1614. X}
  1615. X
  1616. X/* xdolist - special form 'dolist' */
  1617. XLVAL xdolist()
  1618. X{
  1619. X    LVAL list,*argv,clist,sym,val;
  1620. X    CONTEXT cntxt;
  1621. X    int argc;
  1622. X
  1623. X    /* protect some pointers */
  1624. X    xlsave1(list);
  1625. X
  1626. X    /* get the control list (sym list result-expr) */
  1627. X    clist = xlgalist();
  1628. X    sym = match(SYMBOL,&clist);
  1629. X    list = evmatch(LIST,&clist);
  1630. X    argv = xlargv;
  1631. X    argc = xlargc;
  1632. X
  1633. X    /* initialize the local environment */
  1634. X    xlenv = xlframe(xlenv);
  1635. X    xlbind(sym,NIL);
  1636. X
  1637. X    /* establish a new execution context */
  1638. X    xlbegin(&cntxt,CF_RETURN,NIL);
  1639. X    if (setjmp(cntxt.c_jmpbuf))
  1640. X    val = xlvalue;
  1641. X    else {
  1642. X
  1643. X    /* loop through the list */
  1644. X    for (val = NIL; consp(list); list = cdr(list)) {
  1645. X
  1646. X        /* bind the symbol to the next list element */
  1647. X        xlsetvalue(sym,car(list));
  1648. X
  1649. X        /* execute the loop body */
  1650. X        xlargv = argv;
  1651. X        xlargc = argc;
  1652. X        tagbody();
  1653. X    }
  1654. X
  1655. X    /* evaluate the result expression */
  1656. X    xlsetvalue(sym,NIL);
  1657. X    val = (consp(clist) ? xleval(car(clist)) : NIL);
  1658. X
  1659. X    /* unbind the arguments */
  1660. X    xlenv = cdr(xlenv);
  1661. X    }
  1662. X    xlend(&cntxt);
  1663. X
  1664. X    /* restore the stack */
  1665. X    xlpop();
  1666. X
  1667. X    /* return the result */
  1668. X    return (val);
  1669. X}
  1670. X
  1671. X/* xdotimes - special form 'dotimes' */
  1672. XLVAL xdotimes()
  1673. X{
  1674. X    LVAL *argv,clist,sym,cnt,val;
  1675. X    CONTEXT cntxt;
  1676. X    int argc,n,i;
  1677. X
  1678. X    /* get the control list (sym list result-expr) */
  1679. X    clist = xlgalist();
  1680. X    sym = match(SYMBOL,&clist);
  1681. X    cnt = evmatch(FIXNUM,&clist); n = getfixnum(cnt);
  1682. X    argv = xlargv;
  1683. X    argc = xlargc;
  1684. X
  1685. X    /* initialize the local environment */
  1686. X    xlenv = xlframe(xlenv);
  1687. X    xlbind(sym,NIL);
  1688. X
  1689. X    /* establish a new execution context */
  1690. X    xlbegin(&cntxt,CF_RETURN,NIL);
  1691. X    if (setjmp(cntxt.c_jmpbuf))
  1692. X    val = xlvalue;
  1693. X    else {
  1694. X
  1695. X    /* loop through for each value from zero to n-1 */
  1696. X    for (val = NIL, i = 0; i < n; ++i) {
  1697. X
  1698. X        /* bind the symbol to the next list element */
  1699. X        xlsetvalue(sym,cvfixnum((FIXTYPE)i));
  1700. X
  1701. X        /* execute the loop body */
  1702. X        xlargv = argv;
  1703. X        xlargc = argc;
  1704. X        tagbody();
  1705. X    }
  1706. X
  1707. X    /* evaluate the result expression */
  1708. X    xlsetvalue(sym,cnt);
  1709. X    val = (consp(clist) ? xleval(car(clist)) : NIL);
  1710. X
  1711. X    /* unbind the arguments */
  1712. X    xlenv = cdr(xlenv);
  1713. X    }
  1714. X    xlend(&cntxt);
  1715. X
  1716. X    /* return the result */
  1717. X    return (val);
  1718. X}
  1719. X
  1720. X/* xblock - special form 'block' */
  1721. XLVAL xblock()
  1722. X{
  1723. X    LVAL name,val;
  1724. X    CONTEXT cntxt;
  1725. X
  1726. X    /* get the block name */
  1727. X    name = xlgetarg();
  1728. X    if (name && !symbolp(name))
  1729. X    xlbadtype(name);
  1730. X
  1731. X    /* execute the block */
  1732. X    xlbegin(&cntxt,CF_RETURN,name);
  1733. X    if (setjmp(cntxt.c_jmpbuf))
  1734. X    val = xlvalue;
  1735. X    else
  1736. X    for (val = NIL; moreargs(); )
  1737. X        val = xleval(nextarg());
  1738. X    xlend(&cntxt);
  1739. X
  1740. X    /* return the value of the last expression */
  1741. X    return (val);
  1742. X}
  1743. X
  1744. X/* xtagbody - special form 'tagbody' */
  1745. XLVAL xtagbody()
  1746. X{
  1747. X    tagbody();
  1748. X    return (NIL);
  1749. X}
  1750. X
  1751. X/* xcatch - special form 'catch' */
  1752. XLVAL xcatch()
  1753. X{
  1754. X    CONTEXT cntxt;
  1755. X    LVAL tag,val;
  1756. X
  1757. X    /* protect some pointers */
  1758. X    xlsave1(tag);
  1759. X
  1760. X    /* get the tag */
  1761. X    tag = xleval(nextarg());
  1762. X
  1763. X    /* establish an execution context */
  1764. X    xlbegin(&cntxt,CF_THROW,tag);
  1765. X
  1766. X    /* check for 'throw' */
  1767. X    if (setjmp(cntxt.c_jmpbuf))
  1768. X    val = xlvalue;
  1769. X
  1770. X    /* otherwise, evaluate the remainder of the arguments */
  1771. X    else {
  1772. X    for (val = NIL; moreargs(); )
  1773. X        val = xleval(nextarg());
  1774. X    }
  1775. X    xlend(&cntxt);
  1776. X
  1777. X    /* restore the stack */
  1778. X    xlpop();
  1779. X
  1780. X    /* return the result */
  1781. X    return (val);
  1782. X}
  1783. X
  1784. X/* xthrow - special form 'throw' */
  1785. XLVAL xthrow()
  1786. X{
  1787. X    LVAL tag,val;
  1788. X
  1789. X    /* get the tag and value */
  1790. X    tag = xleval(nextarg());
  1791. X    val = (moreargs() ? xleval(nextarg()) : NIL);
  1792. X    xllastarg();
  1793. X
  1794. X    /* throw the tag */
  1795. X    xlthrow(tag,val);
  1796. X}
  1797. X
  1798. X/* xunwindprotect - special form 'unwind-protect' */
  1799. XLVAL xunwindprotect()
  1800. X{
  1801. X    extern CONTEXT *xltarget;
  1802. X    extern int xlmask;
  1803. X    CONTEXT cntxt,*target;
  1804. X    int mask,sts;
  1805. X    LVAL val;
  1806. X
  1807. X    /* protect some pointers */
  1808. X    xlsave1(val);
  1809. X
  1810. X    /* get the expression to protect */
  1811. X    val = xlgetarg();
  1812. X
  1813. X    /* evaluate the protected expression */
  1814. X    xlbegin(&cntxt,CF_UNWIND,NIL);
  1815. X    if (sts = setjmp(cntxt.c_jmpbuf)) {
  1816. X    target = xltarget;
  1817. X    mask = xlmask;
  1818. X    val = xlvalue;
  1819. X    }
  1820. X    else
  1821. X    val = xleval(val);
  1822. X    xlend(&cntxt);
  1823. X    
  1824. X    /* evaluate the cleanup expressions */
  1825. X    while (moreargs())
  1826. X    xleval(nextarg());
  1827. X
  1828. X    /* if unwinding, continue unwinding */
  1829. X    if (sts)
  1830. X    xljump(target,mask,val);
  1831. X
  1832. X    /* restore the stack */
  1833. X    xlpop();
  1834. X
  1835. X    /* return the value of the protected expression */
  1836. X    return (val);
  1837. X}
  1838. X
  1839. X/* xerrset - special form 'errset' */
  1840. XLVAL xerrset()
  1841. X{
  1842. X    LVAL expr,flag,val;
  1843. X    CONTEXT cntxt;
  1844. X
  1845. X    /* get the expression and the print flag */
  1846. X    expr = xlgetarg();
  1847. X    flag = (moreargs() ? xlgetarg() : true);
  1848. X    xllastarg();
  1849. X
  1850. X    /* establish an execution context */
  1851. X    xlbegin(&cntxt,CF_ERROR,flag);
  1852. X
  1853. X    /* check for error */
  1854. X    if (setjmp(cntxt.c_jmpbuf))
  1855. X    val = NIL;
  1856. X
  1857. X    /* otherwise, evaluate the expression */
  1858. X    else {
  1859. X    expr = xleval(expr);
  1860. X    val = consa(expr);
  1861. X    }
  1862. X    xlend(&cntxt);
  1863. X
  1864. X    /* return the result */
  1865. X    return (val);
  1866. X}
  1867. X
  1868. X/* xtrace - special form 'trace' */
  1869. XLVAL xtrace()
  1870. X{
  1871. X    LVAL sym,fun,this;
  1872. X
  1873. X    /* loop through all of the arguments */
  1874. X    sym = xlenter("*TRACELIST*");
  1875. X    while (moreargs()) {
  1876. X    fun = xlgasymbol();
  1877. X
  1878. X    /* check for the function name already being in the list */
  1879. X    for (this = getvalue(sym); consp(this); this = cdr(this))
  1880. X        if (car(this) == fun)
  1881. X        break;
  1882. X
  1883. X    /* add the function name to the list */
  1884. X    if (null(this))
  1885. X        setvalue(sym,cons(fun,getvalue(sym)));
  1886. X    }
  1887. X    return (getvalue(sym));
  1888. X}
  1889. X
  1890. X/* xuntrace - special form 'untrace' */
  1891. XLVAL xuntrace()
  1892. X{
  1893. X    LVAL sym,fun,this,last;
  1894. X
  1895. X    /* loop through all of the arguments */
  1896. X    sym = xlenter("*TRACELIST*");
  1897. X    while (moreargs()) {
  1898. X    fun = xlgasymbol();
  1899. X
  1900. X    /* remove the function name from the list */
  1901. X    last = NIL;
  1902. X    for (this = getvalue(sym); consp(this); this = cdr(this)) {
  1903. X        if (car(this) == fun) {
  1904. X        if (last)
  1905. X            rplacd(last,cdr(this));
  1906. X        else
  1907. X            setvalue(sym,cdr(this));
  1908. X        break;
  1909. X        }
  1910. X        last = this;
  1911. X    }
  1912. X    }
  1913. X    return (getvalue(sym));
  1914. X}
  1915. X
  1916. X/* dobindings - handle bindings for let/let*, prog/prog*, do/do* */
  1917. XLOCAL dobindings(list,env)
  1918. X  LVAL list,env;
  1919. X{
  1920. X    LVAL bnd,sym,val;
  1921. X
  1922. X    /* protect some pointers */
  1923. X    xlsave1(val);
  1924. X
  1925. X    /* bind each symbol in the list of bindings */
  1926. X    for (; consp(list); list = cdr(list)) {
  1927. X
  1928. X    /* get the next binding */
  1929. X    bnd = car(list);
  1930. X
  1931. X    /* handle a symbol */
  1932. X    if (symbolp(bnd)) {
  1933. X        sym = bnd;
  1934. X        val = NIL;
  1935. X    }
  1936. X
  1937. X    /* handle a list of the form (symbol expr) */
  1938. X    else if (consp(bnd)) {
  1939. X        sym = match(SYMBOL,&bnd);
  1940. X        val = evarg(&bnd);
  1941. X    }
  1942. X    else
  1943. X        xlfail("bad binding");
  1944. X
  1945. X    /* bind the value to the symbol */
  1946. X    xlpbind(sym,val,env);
  1947. X    }
  1948. X
  1949. X    /* restore the stack */
  1950. X    xlpop();
  1951. X}
  1952. X
  1953. X/* doupdates - handle updates for do/do* */
  1954. XLOCAL doupdates(list,pflag)
  1955. X  LVAL list; int pflag;
  1956. X{
  1957. X    LVAL plist,bnd,sym,val;
  1958. X
  1959. X    /* protect some pointers */
  1960. X    xlstkcheck(2);
  1961. X    xlsave(plist);
  1962. X    xlsave(val);
  1963. X
  1964. X    /* bind each symbol in the list of bindings */
  1965. X    for (; consp(list); list = cdr(list)) {
  1966. X
  1967. X    /* get the next binding */
  1968. X    bnd = car(list);
  1969. X
  1970. X    /* handle a list of the form (symbol expr) */
  1971. X    if (consp(bnd)) {
  1972. X        sym = match(SYMBOL,&bnd);
  1973. X        bnd = cdr(bnd);
  1974. X        if (bnd) {
  1975. X        val = evarg(&bnd);
  1976. X        if (pflag)
  1977. X            plist = cons(cons(sym,val),plist);
  1978. X        else
  1979. X            xlsetvalue(sym,val);
  1980. X        }
  1981. X    }
  1982. X    }
  1983. X
  1984. X    /* set the values for parallel updates */
  1985. X    for (; plist; plist = cdr(plist))
  1986. X    xlsetvalue(car(car(plist)),cdr(car(plist)));
  1987. X
  1988. X    /* restore the stack */
  1989. X    xlpopn(2);
  1990. X}
  1991. X
  1992. X/* tagbody - execute code within a block and tagbody */
  1993. XLOCAL tagbody()
  1994. X{
  1995. X    LVAL *argv,arg;
  1996. X    CONTEXT cntxt;
  1997. X    int argc;
  1998. X
  1999. X    /* establish an execution context */
  2000. X    xlbegin(&cntxt,CF_GO,NIL);
  2001. X    argc = xlargc;
  2002. X    argv = xlargv;
  2003. X
  2004. X    /* check for a 'go' */
  2005. X    if (setjmp(cntxt.c_jmpbuf)) {
  2006. X    cntxt.c_xlargc = argc;
  2007. X    cntxt.c_xlargv = argv;
  2008. X    }
  2009. X
  2010. X    /* execute the body */
  2011. X    while (moreargs()) {
  2012. X    arg = nextarg();
  2013. X    if (consp(arg))
  2014. X        xleval(arg);
  2015. X    }
  2016. X    xlend(&cntxt);
  2017. X}
  2018. X
  2019. X/* match - get an argument and match its type */
  2020. XLOCAL LVAL match(type,pargs)
  2021. X  int type; LVAL *pargs;
  2022. X{
  2023. X    LVAL arg;
  2024. X
  2025. X    /* make sure the argument exists */
  2026. X    if (!consp(*pargs))
  2027. X    toofew(*pargs);
  2028. X
  2029. X    /* get the argument value */
  2030. X    arg = car(*pargs);
  2031. X
  2032. X    /* move the argument pointer ahead */
  2033. X    *pargs = cdr(*pargs);
  2034. X
  2035. X    /* check its type */
  2036. X    if (type == LIST) {
  2037. X    if (arg && ntype(arg) != CONS)
  2038. X        xlerror("bad argument type",arg);
  2039. X    }
  2040. X    else {
  2041. X    if (arg == NIL || ntype(arg) != type)
  2042. X        xlerror("bad argument type",arg);
  2043. X    }
  2044. X
  2045. X    /* return the argument */
  2046. X    return (arg);
  2047. X}
  2048. X
  2049. X/* evarg - get the next argument and evaluate it */
  2050. XLOCAL LVAL evarg(pargs)
  2051. X  LVAL *pargs;
  2052. X{
  2053. X    LVAL arg;
  2054. X
  2055. X    /* protect some pointers */
  2056. X    xlsave1(arg);
  2057. X
  2058. X    /* make sure the argument exists */
  2059. X    if (!consp(*pargs))
  2060. X    toofew(*pargs);
  2061. X
  2062. X    /* get the argument value */
  2063. X    arg = car(*pargs);
  2064. X
  2065. X    /* move the argument pointer ahead */
  2066. X    *pargs = cdr(*pargs);
  2067. X
  2068. X    /* evaluate the argument */
  2069. X    arg = xleval(arg);
  2070. X
  2071. X    /* restore the stack */
  2072. X    xlpop();
  2073. X
  2074. X    /* return the argument */
  2075. X    return (arg);
  2076. X}
  2077. X
  2078. X/* evmatch - get an evaluated argument and match its type */
  2079. XLOCAL LVAL evmatch(type,pargs)
  2080. X  int type; LVAL *pargs;
  2081. X{
  2082. X    LVAL arg;
  2083. X
  2084. X    /* protect some pointers */
  2085. X    xlsave1(arg);
  2086. X
  2087. X    /* make sure the argument exists */
  2088. X    if (!consp(*pargs))
  2089. X    toofew(*pargs);
  2090. X
  2091. X    /* get the argument value */
  2092. X    arg = car(*pargs);
  2093. X
  2094. X    /* move the argument pointer ahead */
  2095. X    *pargs = cdr(*pargs);
  2096. X
  2097. X    /* evaluate the argument */
  2098. X    arg = xleval(arg);
  2099. X
  2100. X    /* check its type */
  2101. X    if (type == LIST) {
  2102. X    if (arg && ntype(arg) != CONS)
  2103. X        xlerror("bad argument type",arg);
  2104. X    }
  2105. X    else {
  2106. X    if (arg == NIL || ntype(arg) != type)
  2107. X        xlerror("bad argument type",arg);
  2108. X    }
  2109. X
  2110. X    /* restore the stack */
  2111. X    xlpop();
  2112. X
  2113. X    /* return the argument */
  2114. X    return (arg);
  2115. X}
  2116. X
  2117. X/* toofew - too few arguments */
  2118. XLOCAL toofew(args)
  2119. X  LVAL args;
  2120. X{
  2121. X    xlerror("too few arguments",args);
  2122. X}
  2123. X
  2124. X/* toomany - too many arguments */
  2125. XLOCAL toomany(args)
  2126. X  LVAL args;
  2127. X{
  2128. X    xlerror("too many arguments",args);
  2129. X}
  2130. X
  2131. SHAR_EOF
  2132. if test 28157 -ne "`wc -c 'xlcont.c'`"
  2133. then
  2134.     echo shar: error transmitting "'xlcont.c'" '(should have been 28157 characters)'
  2135. fi
  2136. echo shar: extracting "'xldbug.c'" '(3992 characters)'
  2137. if test -f 'xldbug.c'
  2138. then
  2139.     echo shar: over-writing existing file "'xldbug.c'"
  2140. fi
  2141. sed 's/^X//' << \SHAR_EOF > 'xldbug.c'
  2142. X/* xldebug - xlisp debugging support */
  2143. X/*    Copyright (c) 1985, by David Michael Betz
  2144. X    All Rights Reserved
  2145. X    Permission is granted for unrestricted non-commercial use    */
  2146. X
  2147. X#include "xlisp.h"
  2148. X
  2149. X/* external variables */
  2150. Xextern int xldebug;
  2151. Xextern int xlsample;
  2152. Xextern LVAL s_debugio,s_unbound;
  2153. Xextern LVAL s_tracenable,s_tlimit,s_breakenable;
  2154. Xextern LVAL true;
  2155. Xextern char buf[];
  2156. X
  2157. X/* external routines */
  2158. Xextern char *malloc();
  2159. X
  2160. X/* forward declarations */
  2161. XFORWARD LVAL stacktop();
  2162. X
  2163. X/* xlabort - xlisp serious error handler */
  2164. Xxlabort(emsg)
  2165. X  char *emsg;
  2166. X{
  2167. X    xlsignal(emsg,s_unbound);
  2168. X    xlerrprint("error",NULL,emsg,s_unbound);
  2169. X    xlbrklevel();
  2170. X}
  2171. X
  2172. X/* xlbreak - enter a break loop */
  2173. Xxlbreak(emsg,arg)
  2174. X  char *emsg; LVAL arg;
  2175. X{
  2176. X    breakloop("break","return from BREAK",emsg,arg,TRUE);
  2177. X}
  2178. X
  2179. X/* xlfail - xlisp error handler */
  2180. Xxlfail(emsg)
  2181. X  char *emsg;
  2182. X{
  2183. X    xlerror(emsg,s_unbound);
  2184. X}
  2185. X
  2186. X/* xlerror - handle a fatal error */
  2187. Xxlerror(emsg,arg)
  2188. X  char *emsg; LVAL arg;
  2189. X{
  2190. X    if (getvalue(s_breakenable) != NIL)
  2191. X    breakloop("error",NULL,emsg,arg,FALSE);
  2192. X    else {
  2193. X    xlsignal(emsg,arg);
  2194. X    xlerrprint("error",NULL,emsg,arg);
  2195. X    xlbrklevel();
  2196. X    }
  2197. X}
  2198. X
  2199. X/* xlcerror - handle a recoverable error */
  2200. Xxlcerror(cmsg,emsg,arg)
  2201. X  char *cmsg,*emsg; LVAL arg;
  2202. X{
  2203. X    if (getvalue(s_breakenable) != NIL)
  2204. X    breakloop("error",cmsg,emsg,arg,TRUE);
  2205. X    else {
  2206. X    xlsignal(emsg,arg);
  2207. X    xlerrprint("error",NULL,emsg,arg);
  2208. X    xlbrklevel();
  2209. X    }
  2210. X}
  2211. X
  2212. X/* xlerrprint - print an error message */
  2213. Xxlerrprint(hdr,cmsg,emsg,arg)
  2214. X  char *hdr,*cmsg,*emsg; LVAL arg;
  2215. X{
  2216. X    /* print the error message */
  2217. X    sprintf(buf,"%s: %s",hdr,emsg);
  2218. X    errputstr(buf);
  2219. X
  2220. X    /* print the argument */
  2221. X    if (arg != s_unbound) {
  2222. X    errputstr(" - ");
  2223. X    errprint(arg);
  2224. X    }
  2225. X
  2226. X    /* no argument, just end the line */
  2227. X    else
  2228. X    errputstr("\n");
  2229. X
  2230. X    /* print the continuation message */
  2231. X    if (cmsg) {
  2232. X    sprintf(buf,"if continued: %s\n",cmsg);
  2233. X    errputstr(buf);
  2234. X    }
  2235. X}
  2236. X
  2237. X/* breakloop - the debug read-eval-print loop */
  2238. XLOCAL int breakloop(hdr,cmsg,emsg,arg,cflag)
  2239. X  char *hdr,*cmsg,*emsg; LVAL arg; int cflag;
  2240. X{
  2241. X    LVAL expr,val;
  2242. X    CONTEXT cntxt;
  2243. X    int type;
  2244. X
  2245. X    /* print the error message */
  2246. X    xlerrprint(hdr,cmsg,emsg,arg);
  2247. X
  2248. X    /* flush the input buffer */
  2249. X    xlflush();
  2250. X
  2251. X    /* do the back trace */
  2252. X    if (getvalue(s_tracenable)) {
  2253. X    val = getvalue(s_tlimit);
  2254. X    xlbaktrace(fixp(val) ? (int)getfixnum(val) : -1);
  2255. X    }
  2256. X
  2257. X    /* protect some pointers */
  2258. X    xlsave1(expr);
  2259. X
  2260. X    /* increment the debug level */
  2261. X    ++xldebug;
  2262. X
  2263. X    /* debug command processing loop */
  2264. X    xlbegin(&cntxt,CF_BRKLEVEL|CF_CLEANUP|CF_CONTINUE,true);
  2265. X    for (type = 0; type == 0; ) {
  2266. X
  2267. X    /* setup the continue trap */
  2268. X    if (type = setjmp(cntxt.c_jmpbuf))
  2269. X        switch (type) {
  2270. X        case CF_CLEANUP:
  2271. X        continue;
  2272. X        case CF_BRKLEVEL:
  2273. X        type = 0;
  2274. X        break;
  2275. X        case CF_CONTINUE:
  2276. X        if (cflag) {
  2277. X            dbgputstr("[ continue from break loop ]\n");
  2278. X            continue;
  2279. X        }
  2280. X        else xlabort("this error can't be continued");
  2281. X        }
  2282. X
  2283. X    /* print a prompt */
  2284. X    sprintf(buf,"%d> ",xldebug);
  2285. X    dbgputstr(buf);
  2286. X
  2287. X    /* read an expression and check for eof */
  2288. X    if (!xlread(getvalue(s_debugio),&expr,FALSE)) {
  2289. X        type = CF_CLEANUP;
  2290. X        break;
  2291. X    }
  2292. X
  2293. X    /* save the input expression */
  2294. X    xlrdsave(expr);
  2295. X
  2296. X    /* evaluate the expression */
  2297. X    expr = xleval(expr);
  2298. X
  2299. X    /* save the result */
  2300. X    xlevsave(expr);
  2301. X
  2302. X    /* print it */
  2303. X    dbgprint(expr);
  2304. X    }
  2305. X    xlend(&cntxt);
  2306. X
  2307. X    /* decrement the debug level */
  2308. X    --xldebug;
  2309. X
  2310. X    /* restore the stack */
  2311. X    xlpop();
  2312. X
  2313. X    /* check for aborting to the previous level */
  2314. X    if (type == CF_CLEANUP)
  2315. X    xlbrklevel();
  2316. X}
  2317. X
  2318. X/* baktrace - do a back trace */
  2319. Xxlbaktrace(n)
  2320. X  int n;
  2321. X{
  2322. X    LVAL *fp,*p;
  2323. X    int argc;
  2324. X    for (fp = xlfp; (n < 0 || n--) && *fp; fp = fp - (int)getfixnum(*fp)) {
  2325. X    p = fp + 1;
  2326. X    errputstr("Function: ");
  2327. X    errprint(*p++);
  2328. X    if (argc = (int)getfixnum(*p++))
  2329. X        errputstr("Arguments:\n");
  2330. X    while (--argc >= 0) {
  2331. X        errputstr("  ");
  2332. X        errprint(*p++);
  2333. X    }
  2334. X    }
  2335. X}
  2336. X
  2337. X/* xldinit - debug initialization routine */
  2338. Xxldinit()
  2339. X{
  2340. X    xlsample = 0;
  2341. X    xldebug = 0;
  2342. X}
  2343. X
  2344. SHAR_EOF
  2345. if test 3992 -ne "`wc -c 'xldbug.c'`"
  2346. then
  2347.     echo shar: error transmitting "'xldbug.c'" '(should have been 3992 characters)'
  2348. fi
  2349. echo shar: extracting "'xldmem.c'" '(14715 characters)'
  2350. if test -f 'xldmem.c'
  2351. then
  2352.     echo shar: over-writing existing file "'xldmem.c'"
  2353. fi
  2354. sed 's/^X//' << \SHAR_EOF > 'xldmem.c'
  2355. X/* xldmem - xlisp dynamic memory management routines */
  2356. X/*    Copyright (c) 1985, by David Michael Betz
  2357. X    All Rights Reserved
  2358. X    Permission is granted for unrestricted non-commercial use    */
  2359. X
  2360. X#include "xlisp.h"
  2361. X
  2362. X/* node flags */
  2363. X#define MARK    1
  2364. X#define LEFT    2
  2365. X
  2366. X/* macro to compute the size of a segment */
  2367. X#define segsize(n) (sizeof(SEGMENT)+((n)-1)*sizeof(struct node))
  2368. X
  2369. X/* external variables */
  2370. Xextern LVAL obarray,s_gcflag,s_gchook,s_unbound,true;
  2371. Xextern LVAL xlenv,xlfenv,xldenv;
  2372. Xextern char buf[];
  2373. X
  2374. X/* variables local to xldmem.c and xlimage.c */
  2375. XSEGMENT *segs,*lastseg,*fixseg,*charseg;
  2376. Xint anodes,nsegs,gccalls;
  2377. Xlong nnodes,nfree,total;
  2378. XLVAL fnodes;
  2379. X
  2380. X/* external procedures */
  2381. Xextern char *malloc();
  2382. Xextern char *calloc();
  2383. X
  2384. X/* forward declarations */
  2385. XFORWARD LVAL newnode();
  2386. XFORWARD unsigned char *stralloc();
  2387. XFORWARD SEGMENT *newsegment();
  2388. X
  2389. X/* cons - construct a new cons node */
  2390. XLVAL cons(x,y)
  2391. X  LVAL x,y;
  2392. X{
  2393. X    LVAL nnode;
  2394. X
  2395. X    /* get a free node */
  2396. X    if ((nnode = fnodes) == NIL) {
  2397. X    xlstkcheck(2);
  2398. X    xlprotect(x);
  2399. X    xlprotect(y);
  2400. X    findmem();
  2401. X    if ((nnode = fnodes) == NIL)
  2402. X        xlabort("insufficient node space");
  2403. X    xlpop();
  2404. X    xlpop();
  2405. X    }
  2406. X
  2407. X    /* unlink the node from the free list */
  2408. X    fnodes = cdr(nnode);
  2409. X    --nfree;
  2410. X
  2411. X    /* initialize the new node */
  2412. X    nnode->n_type = CONS;
  2413. X    rplaca(nnode,x);
  2414. X    rplacd(nnode,y);
  2415. X
  2416. X    /* return the new node */
  2417. X    return (nnode);
  2418. X}
  2419. X
  2420. X/* cvstring - convert a string to a string node */
  2421. XLVAL cvstring(str)
  2422. X  char *str;
  2423. X{
  2424. X    LVAL val;
  2425. X    xlsave1(val);
  2426. X    val = newnode(STRING);
  2427. X    val->n_strlen = strlen(str) + 1;
  2428. X    val->n_string = stralloc(getslength(val));
  2429. X    strcpy(getstring(val),str);
  2430. X    xlpop();
  2431. X    return (val);
  2432. X}
  2433. X
  2434. X/* newstring - allocate and initialize a new string */
  2435. XLVAL newstring(size)
  2436. X  int size;
  2437. X{
  2438. X    LVAL val;
  2439. X    xlsave1(val);
  2440. X    val = newnode(STRING);
  2441. X    val->n_strlen = size;
  2442. X    val->n_string = stralloc(getslength(val));
  2443. X    strcpy(getstring(val),"");
  2444. X    xlpop();
  2445. X    return (val);
  2446. X}
  2447. X
  2448. X/* cvsymbol - convert a string to a symbol */
  2449. XLVAL cvsymbol(pname)
  2450. X  char *pname;
  2451. X{
  2452. X    LVAL val;
  2453. X    xlsave1(val);
  2454. X    val = newvector(SYMSIZE);
  2455. X    val->n_type = SYMBOL;
  2456. X    setvalue(val,s_unbound);
  2457. X    setfunction(val,s_unbound);
  2458. X    setpname(val,cvstring(pname));
  2459. X    xlpop();
  2460. X    return (val);
  2461. X}
  2462. X
  2463. X/* cvsubr - convert a function to a subr or fsubr */
  2464. XLVAL cvsubr(fcn,type,offset)
  2465. X  LVAL (*fcn)(); int type,offset;
  2466. X{
  2467. X    LVAL val;
  2468. X    val = newnode(type);
  2469. X    val->n_subr = fcn;
  2470. X    val->n_offset = offset;
  2471. X    return (val);
  2472. X}
  2473. X
  2474. X/* cvfile - convert a file pointer to a stream */
  2475. XLVAL cvfile(fp)
  2476. X  FILE *fp;
  2477. X{
  2478. X    LVAL val;
  2479. X    val = newnode(STREAM);
  2480. X    setfile(val,fp);
  2481. X    setsavech(val,'\0');
  2482. X    return (val);
  2483. X}
  2484. X
  2485. X/* cvfixnum - convert an integer to a fixnum node */
  2486. XLVAL cvfixnum(n)
  2487. X  FIXTYPE n;
  2488. X{
  2489. X    LVAL val;
  2490. X    if (n >= SFIXMIN && n <= SFIXMAX)
  2491. X    return (&fixseg->sg_nodes[(int)n-SFIXMIN]);
  2492. X    val = newnode(FIXNUM);
  2493. X    val->n_fixnum = n;
  2494. X    return (val);
  2495. X}
  2496. X
  2497. X/* cvflonum - convert a floating point number to a flonum node */
  2498. XLVAL cvflonum(n)
  2499. X  FLOTYPE n;
  2500. X{
  2501. X    LVAL val;
  2502. X    val = newnode(FLONUM);
  2503. X    val->n_flonum = n;
  2504. X    return (val);
  2505. X}
  2506. X
  2507. X/* cvchar - convert an integer to a character node */
  2508. XLVAL cvchar(n)
  2509. X  int n;
  2510. X{
  2511. X    if (n >= CHARMIN && n <= CHARMAX)
  2512. X    return (&charseg->sg_nodes[n-CHARMIN]);
  2513. X    xlerror("character code out of range",cvfixnum((FIXTYPE)n));
  2514. X}
  2515. X
  2516. X/* newustream - create a new unnamed stream */
  2517. XLVAL newustream()
  2518. X{
  2519. X    LVAL val;
  2520. X    val = newnode(USTREAM);
  2521. X    sethead(val,NIL);
  2522. X    settail(val,NIL);
  2523. X    return (val);
  2524. X}
  2525. X
  2526. X/* newobject - allocate and initialize a new object */
  2527. XLVAL newobject(cls,size)
  2528. X  LVAL cls; int size;
  2529. X{
  2530. X    LVAL val;
  2531. X    val = newvector(size+1);
  2532. X    val->n_type = OBJECT;
  2533. X    setelement(val,0,cls);
  2534. X    return (val);
  2535. X}
  2536. X
  2537. X/* newclosure - allocate and initialize a new closure */
  2538. XLVAL newclosure(name,type,env,fenv)
  2539. X  LVAL name,type,env,fenv;
  2540. X{
  2541. X    LVAL val;
  2542. X    val = newvector(CLOSIZE);
  2543. X    val->n_type = CLOSURE;
  2544. X    setname(val,name);
  2545. X    settype(val,type);
  2546. X    setenv(val,env);
  2547. X    setfenv(val,fenv);
  2548. X    return (val);
  2549. X}
  2550. X
  2551. X/* newstruct - allocate and initialize a new structure node */
  2552. XLVAL newstruct(type,size)
  2553. X  LVAL type; int size;
  2554. X{
  2555. X    LVAL val;
  2556. X    val = newvector(size+1);
  2557. X    val->n_type = STRUCT;
  2558. X    setelement(val,0,type);
  2559. X    return (val);
  2560. X}
  2561. X
  2562. X/* newvector - allocate and initialize a new vector node */
  2563. XLVAL newvector(size)
  2564. X  int size;
  2565. X{
  2566. X    LVAL vect;
  2567. X    int bsize;
  2568. X    xlsave1(vect);
  2569. X    vect = newnode(VECTOR);
  2570. X    vect->n_vsize = 0;
  2571. X    if (bsize = size * sizeof(LVAL)) {
  2572. X    if ((vect->n_vdata = (LVAL *)calloc(1,bsize)) == NULL) {
  2573. X        findmem();
  2574. X        if ((vect->n_vdata = (LVAL *)calloc(1,bsize)) == NULL)
  2575. X        xlfail("insufficient vector space");
  2576. X    }
  2577. X    vect->n_vsize = size;
  2578. X    total += (long) bsize;
  2579. X    }
  2580. X    xlpop();
  2581. X    return (vect);
  2582. X}
  2583. X
  2584. X/* newnode - allocate a new node */
  2585. XLOCAL LVAL newnode(type)
  2586. X  int type;
  2587. X{
  2588. X    LVAL nnode;
  2589. X
  2590. X    /* get a free node */
  2591. X    if ((nnode = fnodes) == NIL) {
  2592. X    findmem();
  2593. X    if ((nnode = fnodes) == NIL)
  2594. X        xlabort("insufficient node space");
  2595. X    }
  2596. X
  2597. X    /* unlink the node from the free list */
  2598. X    fnodes = cdr(nnode);
  2599. X    nfree -= 1L;
  2600. X
  2601. X    /* initialize the new node */
  2602. X    nnode->n_type = type;
  2603. X    rplacd(nnode,NIL);
  2604. X
  2605. X    /* return the new node */
  2606. X    return (nnode);
  2607. X}
  2608. X
  2609. X/* stralloc - allocate memory for a string adding a byte for the terminator */
  2610. XLOCAL unsigned char *stralloc(size)
  2611. X  int size;
  2612. X{
  2613. X    unsigned char *sptr;
  2614. X
  2615. X    /* allocate memory for the string copy */
  2616. X    if ((sptr = (unsigned char *)malloc(size)) == NULL) {
  2617. X    gc();  
  2618. X    if ((sptr = (unsigned char *)malloc(size)) == NULL)
  2619. X        xlfail("insufficient string space");
  2620. X    }
  2621. X    total += (long)size;
  2622. X
  2623. X    /* return the new string memory */
  2624. X    return (sptr);
  2625. X}
  2626. X
  2627. X/* findmem - find more memory by collecting then expanding */
  2628. XLOCAL findmem()
  2629. X{
  2630. X    gc();
  2631. X    if (nfree < (long)anodes)
  2632. X    addseg();
  2633. X}
  2634. X
  2635. X/* gc - garbage collect (only called here and in xlimage.c) */
  2636. Xgc()
  2637. X{
  2638. X    register LVAL **p,*ap,tmp;
  2639. X    char buf[STRMAX+1];
  2640. X    LVAL *newfp,fun;
  2641. X
  2642. X    /* print the start of the gc message */
  2643. X    if (s_gcflag && getvalue(s_gcflag)) {
  2644. X    sprintf(buf,"[ gc: total %ld, ",nnodes);
  2645. X    stdputstr(buf);
  2646. X    }
  2647. X
  2648. X    /* mark the obarray, the argument list and the current environment */
  2649. X    if (obarray)
  2650. X    mark(obarray);
  2651. X    if (xlenv)
  2652. X    mark(xlenv);
  2653. X    if (xlfenv)
  2654. X    mark(xlfenv);
  2655. X    if (xldenv)
  2656. X    mark(xldenv);
  2657. X
  2658. X    /* mark the evaluation stack */
  2659. X    for (p = xlstack; p < xlstktop; ++p)
  2660. X    if (tmp = **p)
  2661. X        mark(tmp);
  2662. X
  2663. X    /* mark the argument stack */
  2664. X    for (ap = xlargstkbase; ap < xlsp; ++ap)
  2665. X    if (tmp = *ap)
  2666. X        mark(tmp);
  2667. X
  2668. X    /* sweep memory collecting all unmarked nodes */
  2669. X    sweep();
  2670. X
  2671. X    /* count the gc call */
  2672. X    ++gccalls;
  2673. X
  2674. X    /* call the *gc-hook* if necessary */
  2675. X    if (s_gchook && (fun = getvalue(s_gchook))) {
  2676. X    newfp = xlsp;
  2677. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  2678. X    pusharg(fun);
  2679. X    pusharg(cvfixnum((FIXTYPE)2));
  2680. X    pusharg(cvfixnum((FIXTYPE)nnodes));
  2681. X    pusharg(cvfixnum((FIXTYPE)nfree));
  2682. X    xlfp = newfp;
  2683. X    xlapply(2);
  2684. X    }
  2685. X
  2686. X    /* print the end of the gc message */
  2687. X    if (s_gcflag && getvalue(s_gcflag)) {
  2688. X    sprintf(buf,"%ld free ]\n",nfree);
  2689. X    stdputstr(buf);
  2690. X    }
  2691. X}
  2692. X
  2693. X/* mark - mark all accessible nodes */
  2694. XLOCAL mark(ptr)
  2695. X  LVAL ptr;
  2696. X{
  2697. X    register LVAL this,prev,tmp;
  2698. X    int type,i,n;
  2699. X
  2700. X    /* initialize */
  2701. X    prev = NIL;
  2702. X    this = ptr;
  2703. X
  2704. X    /* mark this list */
  2705. X    for (;;) {
  2706. X
  2707. X    /* descend as far as we can */
  2708. X    while (!(this->n_flags & MARK))
  2709. X
  2710. X        /* check cons and unnamed stream nodes */
  2711. X        if ((type = ntype(this)) == CONS || type == USTREAM) {
  2712. X        if (tmp = car(this)) {
  2713. X            this->n_flags |= MARK|LEFT;
  2714. X            rplaca(this,prev);
  2715. X        }
  2716. X        else if (tmp = cdr(this)) {
  2717. X            this->n_flags |= MARK;
  2718. X            rplacd(this,prev);
  2719. X        }
  2720. X        else {                /* both sides nil */
  2721. X            this->n_flags |= MARK;
  2722. X            break;
  2723. X        }
  2724. X        prev = this;            /* step down the branch */
  2725. X        this = tmp;
  2726. X        }
  2727. X
  2728. X        /* mark other node types */
  2729. X        else {
  2730. X        this->n_flags |= MARK;
  2731. X        switch (type) {
  2732. X        case SYMBOL:
  2733. X        case OBJECT:
  2734. X        case VECTOR:
  2735. X        case CLOSURE:
  2736. X        case STRUCT:
  2737. X            for (i = 0, n = getsize(this); --n >= 0; ++i)
  2738. X            if (tmp = getelement(this,i))
  2739. X                mark(tmp);
  2740. X            break;
  2741. X        }
  2742. X        break;
  2743. X        }
  2744. X
  2745. X    /* backup to a point where we can continue descending */
  2746. X    for (;;)
  2747. X
  2748. X        /* make sure there is a previous node */
  2749. X        if (prev) {
  2750. X        if (prev->n_flags & LEFT) {    /* came from left side */
  2751. X            prev->n_flags &= ~LEFT;
  2752. X            tmp = car(prev);
  2753. X            rplaca(prev,this);
  2754. X            if (this = cdr(prev)) {
  2755. X            rplacd(prev,tmp);            
  2756. X            break;
  2757. X            }
  2758. X        }
  2759. X        else {                /* came from right side */
  2760. X            tmp = cdr(prev);
  2761. X            rplacd(prev,this);
  2762. X        }
  2763. X        this = prev;            /* step back up the branch */
  2764. X        prev = tmp;
  2765. X        }
  2766. X
  2767. X        /* no previous node, must be done */
  2768. X        else
  2769. X        return;
  2770. X    }
  2771. X}
  2772. X
  2773. X/* sweep - sweep all unmarked nodes and add them to the free list */
  2774. XLOCAL sweep()
  2775. X{
  2776. X    SEGMENT *seg;
  2777. X    LVAL p;
  2778. X    int n;
  2779. X
  2780. X    /* empty the free list */
  2781. X    fnodes = NIL;
  2782. X    nfree = 0L;
  2783. X
  2784. X    /* add all unmarked nodes */
  2785. X    for (seg = segs; seg; seg = seg->sg_next) {
  2786. X    if (seg == fixseg)     /* don't sweep the fixnum segment */
  2787. X        continue;
  2788. X    else if (seg == charseg) /* don't sweep the character segment */
  2789. X        continue;
  2790. X    p = &seg->sg_nodes[0];
  2791. X    for (n = seg->sg_size; --n >= 0; ++p)
  2792. X        if (!(p->n_flags & MARK)) {
  2793. X        switch (ntype(p)) {
  2794. X        case STRING:
  2795. X            if (getstring(p) != NULL) {
  2796. X                total -= (long)getslength(p);
  2797. X                free(getstring(p));
  2798. X            }
  2799. X            break;
  2800. X        case STREAM:
  2801. X            if (getfile(p))
  2802. X                osclose(getfile(p));
  2803. X            break;
  2804. X        case SYMBOL:
  2805. X        case OBJECT:
  2806. X        case VECTOR:
  2807. X        case CLOSURE:
  2808. X        case STRUCT:
  2809. X            if (p->n_vsize) {
  2810. X                total -= (long) (p->n_vsize * sizeof(LVAL));
  2811. X                free(p->n_vdata);
  2812. X            }
  2813. X            break;
  2814. X        }
  2815. X        p->n_type = FREE;
  2816. X        rplaca(p,NIL);
  2817. X        rplacd(p,fnodes);
  2818. X        fnodes = p;
  2819. X        nfree += 1L;
  2820. X        }
  2821. X        else
  2822. X        p->n_flags &= ~MARK;
  2823. X    }
  2824. X}
  2825. X
  2826. X/* addseg - add a segment to the available memory */
  2827. XLOCAL int addseg()
  2828. X{
  2829. X    SEGMENT *newseg;
  2830. X    LVAL p;
  2831. X    int n;
  2832. X
  2833. X    /* allocate the new segment */
  2834. X    if (anodes == 0 || (newseg = newsegment(anodes)) == NULL)
  2835. X    return (FALSE);
  2836. X
  2837. X    /* add each new node to the free list */
  2838. X    p = &newseg->sg_nodes[0];
  2839. X    for (n = anodes; --n >= 0; ++p) {
  2840. X    rplacd(p,fnodes);
  2841. X    fnodes = p;
  2842. X    }
  2843. X
  2844. X    /* return successfully */
  2845. X    return (TRUE);
  2846. X}
  2847. X
  2848. X/* newsegment - create a new segment (only called here and in xlimage.c) */
  2849. XSEGMENT *newsegment(n)
  2850. X  int n;
  2851. X{
  2852. X    SEGMENT *newseg;
  2853. X
  2854. X    /* allocate the new segment */
  2855. X    if ((newseg = (SEGMENT *)calloc(1,segsize(n))) == NULL)
  2856. X    return (NULL);
  2857. X
  2858. X    /* initialize the new segment */
  2859. X    newseg->sg_size = n;
  2860. X    newseg->sg_next = NULL;
  2861. X    if (segs)
  2862. X    lastseg->sg_next = newseg;
  2863. X    else
  2864. X    segs = newseg;
  2865. X    lastseg = newseg;
  2866. X
  2867. X    /* update the statistics */
  2868. X    total += (long)segsize(n);
  2869. X    nnodes += (long)n;
  2870. X    nfree += (long)n;
  2871. X    ++nsegs;
  2872. X
  2873. X    /* return the new segment */
  2874. X    return (newseg);
  2875. X}
  2876. X/* stats - print memory statistics */
  2877. XLOCAL stats()
  2878. X{
  2879. X    sprintf(buf,"Nodes:       %ld\n",nnodes); stdputstr(buf);
  2880. X    sprintf(buf,"Free nodes:  %ld\n",nfree);  stdputstr(buf);
  2881. X    sprintf(buf,"Segments:    %d\n",nsegs);   stdputstr(buf);
  2882. X    sprintf(buf,"Allocate:    %d\n",anodes);  stdputstr(buf);
  2883. X    sprintf(buf,"Total:       %ld\n",total);  stdputstr(buf);
  2884. X    sprintf(buf,"Collections: %d\n",gccalls); stdputstr(buf);
  2885. X}
  2886. X
  2887. X/* xgc - xlisp function to force garbage collection */
  2888. XLVAL xgc()
  2889. X{
  2890. X    /* make sure there aren't any arguments */
  2891. X    xllastarg();
  2892. X
  2893. X    /* garbage collect */
  2894. X    gc();
  2895. X
  2896. X    /* return nil */
  2897. X    return (NIL);
  2898. X}
  2899. X
  2900. X/* xexpand - xlisp function to force memory expansion */
  2901. XLVAL xexpand()
  2902. X{
  2903. X    LVAL num;
  2904. X    int n,i;
  2905. X
  2906. X    /* get the new number to allocate */
  2907. X    if (moreargs()) {
  2908. X    num = xlgafixnum();
  2909. X    n = getfixnum(num);
  2910. X    }
  2911. X    else
  2912. X    n = 1;
  2913. X    xllastarg();
  2914. X
  2915. X    /* allocate more segments */
  2916. X    for (i = 0; i < n; i++)
  2917. X    if (!addseg())
  2918. X        break;
  2919. X
  2920. X    /* return the number of segments added */
  2921. X    return (cvfixnum((FIXTYPE)i));
  2922. X}
  2923. X
  2924. X/* xalloc - xlisp function to set the number of nodes to allocate */
  2925. XLVAL xalloc()
  2926. X{
  2927. X    int n,oldn;
  2928. X    LVAL num;
  2929. X
  2930. X    /* get the new number to allocate */
  2931. X    num = xlgafixnum();
  2932. X    n = getfixnum(num);
  2933. X
  2934. X    /* make sure there aren't any more arguments */
  2935. X    xllastarg();
  2936. X
  2937. X    /* set the new number of nodes to allocate */
  2938. X    oldn = anodes;
  2939. X    anodes = n;
  2940. X
  2941. X    /* return the old number */
  2942. X    return (cvfixnum((FIXTYPE)oldn));
  2943. X}
  2944. X
  2945. X/* xmem - xlisp function to print memory statistics */
  2946. XLVAL xmem()
  2947. X{
  2948. X    /* allow one argument for compatiblity with common lisp */
  2949. X    if (moreargs()) xlgetarg();
  2950. X    xllastarg();
  2951. X
  2952. X    /* print the statistics */
  2953. X    stats();
  2954. X
  2955. X    /* return nil */
  2956. X    return (NIL);
  2957. X}
  2958. X
  2959. X#ifdef SAVERESTORE
  2960. X/* xsave - save the memory image */
  2961. XLVAL xsave()
  2962. X{
  2963. X    unsigned char *name;
  2964. X
  2965. X    /* get the file name, verbose flag and print flag */
  2966. X    name = getstring(xlgetfname());
  2967. X    xllastarg();
  2968. X
  2969. X    /* save the memory image */
  2970. X    return (xlisave(name) ? true : NIL);
  2971. X}
  2972. X
  2973. X/* xrestore - restore a saved memory image */
  2974. XLVAL xrestore()
  2975. X{
  2976. X    extern jmp_buf top_level;
  2977. X    unsigned char *name;
  2978. X
  2979. X    /* get the file name, verbose flag and print flag */
  2980. X    name = getstring(xlgetfname());
  2981. X    xllastarg();
  2982. X
  2983. X    /* restore the saved memory image */
  2984. X    if (!xlirestore(name))
  2985. X    return (NIL);
  2986. X
  2987. X    /* return directly to the top level */
  2988. X    stdputstr("[ returning to the top level ]\n");
  2989. X    longjmp(top_level,1);
  2990. X}
  2991. X#endif
  2992. X
  2993. X/* xlminit - initialize the dynamic memory module */
  2994. Xxlminit()
  2995. X{
  2996. X    LVAL p;
  2997. X    int i;
  2998. X
  2999. X    /* initialize our internal variables */
  3000. X    segs = lastseg = NULL;
  3001. X    nnodes = nfree = total = 0L;
  3002. X    nsegs = gccalls = 0;
  3003. X    anodes = NNODES;
  3004. X    fnodes = NIL;
  3005. X
  3006. X    /* allocate the fixnum segment */
  3007. X    if ((fixseg = newsegment(SFIXSIZE)) == NULL)
  3008. X    xlfatal("insufficient memory");
  3009. X
  3010. X    /* initialize the fixnum segment */
  3011. X    p = &fixseg->sg_nodes[0];
  3012. X    for (i = SFIXMIN; i <= SFIXMAX; ++i) {
  3013. X    p->n_type = FIXNUM;
  3014. X    p->n_fixnum = i;
  3015. X    ++p;
  3016. X    }
  3017. X
  3018. X    /* allocate the character segment */
  3019. X    if ((charseg = newsegment(CHARSIZE)) == NULL)
  3020. X    xlfatal("insufficient memory");
  3021. X
  3022. X    /* initialize the character segment */
  3023. X    p = &charseg->sg_nodes[0];
  3024. X    for (i = CHARMIN; i <= CHARMAX; ++i) {
  3025. X    p->n_type = CHAR;
  3026. X    p->n_chcode = i;
  3027. X    ++p;
  3028. X    }
  3029. X
  3030. X    /* initialize structures that are marked by the collector */
  3031. X    obarray = xlenv = xlfenv = xldenv = NIL;
  3032. X    s_gcflag = s_gchook = NIL;
  3033. X
  3034. X    /* allocate the evaluation stack */
  3035. X    if ((xlstkbase = (LVAL **)malloc(EDEPTH * sizeof(LVAL *))) == NULL)
  3036. X    xlfatal("insufficient memory");
  3037. X    xlstack = xlstktop = xlstkbase + EDEPTH;
  3038. X
  3039. X    /* allocate the argument stack */
  3040. X    if ((xlargstkbase = (LVAL *)malloc(ADEPTH * sizeof(LVAL))) == NULL)
  3041. X    xlfatal("insufficient memory");
  3042. X    xlargstktop = xlargstkbase + ADEPTH;
  3043. X    xlfp = xlsp = xlargstkbase;
  3044. X    *xlsp++ = NIL;
  3045. X}
  3046. X
  3047. SHAR_EOF
  3048. if test 14715 -ne "`wc -c 'xldmem.c'`"
  3049. then
  3050.     echo shar: error transmitting "'xldmem.c'" '(should have been 14715 characters)'
  3051. fi
  3052. echo shar: extracting "'xldmem.h'" '(6120 characters)'
  3053. if test -f 'xldmem.h'
  3054. then
  3055.     echo shar: over-writing existing file "'xldmem.h'"
  3056. fi
  3057. sed 's/^X//' << \SHAR_EOF > 'xldmem.h'
  3058. X/* xldmem.h - dynamic memory definitions */
  3059. X/*    Copyright (c) 1987, by David Michael Betz
  3060. X    All Rights Reserved
  3061. X    Permission is granted for unrestricted non-commercial use    */
  3062. X
  3063. X/* small fixnum range */
  3064. X#define SFIXMIN        (-128)
  3065. X#define SFIXMAX        255
  3066. X#define SFIXSIZE    384
  3067. X
  3068. X/* character range */
  3069. X#define CHARMIN        0
  3070. X#define CHARMAX        255
  3071. X#define CHARSIZE    256
  3072. X
  3073. X/* new node access macros */
  3074. X#define ntype(x)    ((x)->n_type)
  3075. X
  3076. X/* cons access macros */
  3077. X#define car(x)        ((x)->n_car)
  3078. X#define cdr(x)        ((x)->n_cdr)
  3079. X#define rplaca(x,y)    ((x)->n_car = (y))
  3080. X#define rplacd(x,y)    ((x)->n_cdr = (y))
  3081. X
  3082. X/* symbol access macros */
  3083. X#define getvalue(x)     ((x)->n_vdata[0])
  3084. X#define setvalue(x,v)     ((x)->n_vdata[0] = (v))
  3085. X#define getfunction(x)     ((x)->n_vdata[1])
  3086. X#define setfunction(x,v) ((x)->n_vdata[1] = (v))
  3087. X#define getplist(x)     ((x)->n_vdata[2])
  3088. X#define setplist(x,v)     ((x)->n_vdata[2] = (v))
  3089. X#define getpname(x)     ((x)->n_vdata[3])
  3090. X#define setpname(x,v)     ((x)->n_vdata[3] = (v))
  3091. X#define SYMSIZE        4
  3092. X
  3093. X/* closure access macros */
  3094. X#define getname(x)         ((x)->n_vdata[0])
  3095. X#define setname(x,v)       ((x)->n_vdata[0] = (v))
  3096. X#define gettype(x)        ((x)->n_vdata[1])
  3097. X#define settype(x,v)      ((x)->n_vdata[1] = (v))
  3098. X#define getargs(x)         ((x)->n_vdata[2])
  3099. X#define setargs(x,v)       ((x)->n_vdata[2] = (v))
  3100. X#define getoargs(x)        ((x)->n_vdata[3])
  3101. X#define setoargs(x,v)      ((x)->n_vdata[3] = (v))
  3102. X#define getrest(x)         ((x)->n_vdata[4])
  3103. X#define setrest(x,v)       ((x)->n_vdata[4] = (v))
  3104. X#define getkargs(x)        ((x)->n_vdata[5])
  3105. X#define setkargs(x,v)      ((x)->n_vdata[5] = (v))
  3106. X#define getaargs(x)        ((x)->n_vdata[6])
  3107. X#define setaargs(x,v)      ((x)->n_vdata[6] = (v))
  3108. X#define getbody(x)         ((x)->n_vdata[7])
  3109. X#define setbody(x,v)       ((x)->n_vdata[7] = (v))
  3110. X#define getenv(x)    ((x)->n_vdata[8])
  3111. X#define setenv(x,v)    ((x)->n_vdata[8] = (v))
  3112. X#define getfenv(x)    ((x)->n_vdata[9])
  3113. X#define setfenv(x,v)    ((x)->n_vdata[9] = (v))
  3114. X#define getlambda(x)    ((x)->n_vdata[10])
  3115. X#define setlambda(x,v)    ((x)->n_vdata[10] = (v))
  3116. X#define CLOSIZE        11
  3117. X
  3118. X/* vector access macros */
  3119. X#define getsize(x)    ((x)->n_vsize)
  3120. X#define getelement(x,i)    ((x)->n_vdata[i])
  3121. X#define setelement(x,i,v) ((x)->n_vdata[i] = (v))
  3122. X
  3123. X/* object access macros */
  3124. X#define getclass(x)    ((x)->n_vdata[0])
  3125. X#define getivar(x,i)    ((x)->n_vdata[i+1])
  3126. X#define setivar(x,i,v)    ((x)->n_vdata[i+1] = (v))
  3127. X
  3128. X/* subr/fsubr access macros */
  3129. X#define getsubr(x)    ((x)->n_subr)
  3130. X#define getoffset(x)    ((x)->n_offset)
  3131. X
  3132. X/* fixnum/flonum/char access macros */
  3133. X#define getfixnum(x)    ((x)->n_fixnum)
  3134. X#define getflonum(x)    ((x)->n_flonum)
  3135. X#define getchcode(x)    ((x)->n_chcode)
  3136. X
  3137. X/* string access macros */
  3138. X#define getstring(x)    ((x)->n_string)
  3139. X#define getslength(x)    ((x)->n_strlen)
  3140. X
  3141. X/* file stream access macros */
  3142. X#define getfile(x)    ((x)->n_fp)
  3143. X#define setfile(x,v)    ((x)->n_fp = (v))
  3144. X#define getsavech(x)    ((x)->n_savech)
  3145. X#define setsavech(x,v)    ((x)->n_savech = (v))
  3146. X
  3147. X/* unnamed stream access macros */
  3148. X#define gethead(x)    ((x)->n_car)
  3149. X#define sethead(x,v)    ((x)->n_car = (v))
  3150. X#define gettail(x)    ((x)->n_cdr)
  3151. X#define settail(x,v)    ((x)->n_cdr = (v))
  3152. X
  3153. X/* node types */
  3154. X#define FREE    0
  3155. X#define SUBR    1
  3156. X#define FSUBR    2
  3157. X#define CONS    3
  3158. X#define SYMBOL    4
  3159. X#define FIXNUM    5
  3160. X#define FLONUM    6
  3161. X#define STRING    7
  3162. X#define OBJECT    8
  3163. X#define STREAM    9
  3164. X#define VECTOR    10
  3165. X#define CLOSURE    11
  3166. X#define CHAR    12
  3167. X#define USTREAM    13
  3168. X#define STRUCT    14
  3169. X
  3170. X/* subr/fsubr node */
  3171. X#define n_subr        n_info.n_xsubr.xs_subr
  3172. X#define n_offset    n_info.n_xsubr.xs_offset
  3173. X
  3174. X/* cons node */
  3175. X#define n_car        n_info.n_xcons.xc_car
  3176. X#define n_cdr        n_info.n_xcons.xc_cdr
  3177. X
  3178. X/* fixnum node */
  3179. X#define n_fixnum    n_info.n_xfixnum.xf_fixnum
  3180. X
  3181. X/* flonum node */
  3182. X#define n_flonum    n_info.n_xflonum.xf_flonum
  3183. X/* character node */
  3184. X#define n_chcode    n_info.n_xchar.xc_chcode
  3185. X
  3186. X/* string node */
  3187. X#define n_string    n_info.n_xstring.xs_string
  3188. X#define n_strlen    n_info.n_xstring.xs_length
  3189. X
  3190. X/* stream node */
  3191. X#define n_fp        n_info.n_xstream.xs_fp
  3192. X#define n_savech    n_info.n_xstream.xs_savech
  3193. X
  3194. X/* vector/object node */
  3195. X#define n_vsize        n_info.n_xvector.xv_size
  3196. X#define n_vdata        n_info.n_xvector.xv_data
  3197. X
  3198. X/* node structure */
  3199. Xtypedef struct node {
  3200. X    char n_type;        /* type of node */
  3201. X    char n_flags;        /* flag bits */
  3202. X    union ninfo {         /* value */
  3203. X    struct xsubr {        /* subr/fsubr node */
  3204. X        struct node *(*xs_subr)();    /* function pointer */
  3205. X        int xs_offset;        /* offset into funtab */
  3206. X    } n_xsubr;
  3207. X    struct xcons {        /* cons node */
  3208. X        struct node *xc_car;    /* the car pointer */
  3209. X        struct node *xc_cdr;    /* the cdr pointer */
  3210. X    } n_xcons;
  3211. X    struct xfixnum {    /* fixnum node */
  3212. X        FIXTYPE xf_fixnum;        /* fixnum value */
  3213. X    } n_xfixnum;
  3214. X    struct xflonum {    /* flonum node */
  3215. X        FLOTYPE xf_flonum;        /* flonum value */
  3216. X    } n_xflonum;
  3217. X    struct xchar {        /* character node */
  3218. X        int xc_chcode;        /* character code */
  3219. X    } n_xchar;
  3220. X    struct xstring {    /* string node */
  3221. X        int xs_length;        /* string length */
  3222. X        unsigned char *xs_string;    /* string pointer */
  3223. X    } n_xstring;
  3224. X    struct xstream {     /* stream node */
  3225. X        FILE *xs_fp;        /* the file pointer */
  3226. X        int xs_savech;        /* lookahead character */
  3227. X    } n_xstream;
  3228. X    struct xvector {    /* vector/object/symbol/structure node */
  3229. X        int xv_size;        /* vector size */
  3230. X        struct node **xv_data;    /* vector data */
  3231. X    } n_xvector;
  3232. X    } n_info;
  3233. X} *LVAL;
  3234. X
  3235. X/* memory segment structure definition */
  3236. Xtypedef struct segment {
  3237. X    int sg_size;
  3238. X    struct segment *sg_next;
  3239. X    struct node sg_nodes[1];
  3240. X} SEGMENT;
  3241. X
  3242. X/* memory allocation functions */
  3243. Xextern LVAL cons();        /* (cons x y) */
  3244. Xextern LVAL cvsymbol();           /* convert a string to a symbol */
  3245. Xextern LVAL cvstring();           /* convert a string */
  3246. Xextern LVAL cvfile();        /* convert a FILE * to a file */
  3247. Xextern LVAL cvsubr();        /* convert a function to a subr/fsubr */
  3248. Xextern LVAL cvfixnum();           /* convert a fixnum */
  3249. Xextern LVAL cvflonum();           /* convert a flonum */
  3250. Xextern LVAL cvchar();        /* convert a character */
  3251. X
  3252. Xextern LVAL newstring();    /* create a new string */
  3253. Xextern LVAL newvector();    /* create a new vector */
  3254. Xextern LVAL newobject();    /* create a new object */
  3255. Xextern LVAL newclosure();    /* create a new closure */
  3256. Xextern LVAL newustream();    /* create a new unnamed stream */
  3257. Xextern LVAL newstruct();    /* create a new structure */
  3258. X
  3259. SHAR_EOF
  3260. if test 6120 -ne "`wc -c 'xldmem.h'`"
  3261. then
  3262.     echo shar: error transmitting "'xldmem.h'" '(should have been 6120 characters)'
  3263. fi
  3264. echo shar: extracting "'xleval.c'" '(19240 characters)'
  3265. if test -f 'xleval.c'
  3266. then
  3267.     echo shar: over-writing existing file "'xleval.c'"
  3268. fi
  3269. sed 's/^X//' << \SHAR_EOF > 'xleval.c'
  3270. X/* xleval - xlisp evaluator */
  3271. X/*    Copyright (c) 1985, by David Michael Betz
  3272. X    All Rights Reserved
  3273. X    Permission is granted for unrestricted non-commercial use    */
  3274. X
  3275. X#include "xlisp.h"
  3276. X
  3277. X/* macro to check for lambda list keywords */
  3278. X#define iskey(s) ((s) == lk_optional \
  3279. X               || (s) == lk_rest \
  3280. X               || (s) == lk_key \
  3281. X               || (s) == lk_aux \
  3282. X               || (s) == lk_allow_other_keys)
  3283. X
  3284. X/* macros to handle tracing */
  3285. X#define trenter(sym,argc,argv) {if (sym) doenter(sym,argc,argv);}
  3286. X#define trexit(sym,val) {if (sym) doexit(sym,val);}
  3287. X
  3288. X/* external variables */
  3289. Xextern LVAL xlenv,xlfenv,xldenv,xlvalue,true;
  3290. Xextern LVAL lk_optional,lk_rest,lk_key,lk_aux,lk_allow_other_keys;
  3291. Xextern LVAL s_evalhook,s_applyhook,s_tracelist;
  3292. Xextern LVAL s_lambda,s_macro;
  3293. Xextern LVAL s_unbound;
  3294. Xextern int xlsample;
  3295. Xextern char buf[];
  3296. X
  3297. X/* forward declarations */
  3298. XFORWARD LVAL xlxeval();
  3299. XFORWARD LVAL evalhook();
  3300. XFORWARD LVAL evform();
  3301. XFORWARD LVAL evfun();
  3302. X
  3303. X/* xleval - evaluate an xlisp expression (checking for *evalhook*) */
  3304. XLVAL xleval(expr)
  3305. X  LVAL expr;
  3306. X{
  3307. X    /* check for control codes */
  3308. X    if (--xlsample <= 0) {
  3309. X    xlsample = SAMPLE;
  3310. X    oscheck();
  3311. X    }
  3312. X
  3313. X    /* check for *evalhook* */
  3314. X    if (getvalue(s_evalhook))
  3315. X    return (evalhook(expr));
  3316. X
  3317. X    /* check for nil */
  3318. X    if (null(expr))
  3319. X    return (NIL);
  3320. X
  3321. X    /* dispatch on the node type */
  3322. X    switch (ntype(expr)) {
  3323. X    case CONS:
  3324. X    return (evform(expr));
  3325. X    case SYMBOL:
  3326. X    return (xlgetvalue(expr));
  3327. X    default:
  3328. X    return (expr);
  3329. X    }
  3330. X}
  3331. X
  3332. X/* xlevalenv - evaluate an expression in a specified environment */
  3333. XLVAL xlevalenv(expr,env,fenv)
  3334. X  LVAL expr,env,fenv;
  3335. X{
  3336. X    LVAL oldenv,oldfenv,val;
  3337. X
  3338. X    /* protect some pointers */
  3339. X    xlstkcheck(2);
  3340. X    xlsave(oldenv);
  3341. X    xlsave(oldfenv);
  3342. X
  3343. X    /* establish the new environment */
  3344. X    oldenv = xlenv;
  3345. X    oldfenv = xlfenv;
  3346. X    xlenv = env;
  3347. X    xlfenv = fenv;
  3348. X
  3349. X    /* evaluate the expression */
  3350. X    val = xleval(expr);
  3351. X
  3352. X    /* restore the environment */
  3353. X    xlenv = oldenv;
  3354. X    xlfenv = oldfenv;
  3355. X
  3356. X    /* restore the stack */
  3357. X    xlpopn(2);
  3358. X
  3359. X    /* return the result value */
  3360. X    return (val);
  3361. X}
  3362. X
  3363. X/* xlxeval - evaluate an xlisp expression (bypassing *evalhook*) */
  3364. XLVAL xlxeval(expr)
  3365. X  LVAL expr;
  3366. X{
  3367. X    /* check for nil */
  3368. X    if (null(expr))
  3369. X    return (NIL);
  3370. X
  3371. X    /* dispatch on node type */
  3372. X    switch (ntype(expr)) {
  3373. X    case CONS:
  3374. X    return (evform(expr));
  3375. X    case SYMBOL:
  3376. X    return (xlgetvalue(expr));
  3377. X    default:
  3378. X    return (expr);
  3379. X    }
  3380. X}
  3381. X
  3382. X/* xlapply - apply a function to arguments (already on the stack) */
  3383. XLVAL xlapply(argc)
  3384. X  int argc;
  3385. X{
  3386. X    LVAL *oldargv,fun,val;
  3387. X    int oldargc;
  3388. X    
  3389. X    /* get the function */
  3390. X    fun = xlfp[1];
  3391. X
  3392. X    /* get the functional value of symbols */
  3393. X    if (symbolp(fun)) {
  3394. X    while ((val = getfunction(fun)) == s_unbound)
  3395. X        xlfunbound(fun);
  3396. X    fun = xlfp[1] = val;
  3397. X    }
  3398. X
  3399. X    /* check for nil */
  3400. X    if (null(fun))
  3401. X    xlerror("bad function",fun);
  3402. X
  3403. X    /* dispatch on node type */
  3404. X    switch (ntype(fun)) {
  3405. X    case SUBR:
  3406. X    oldargc = xlargc;
  3407. X    oldargv = xlargv;
  3408. X    xlargc = argc;
  3409. X    xlargv = xlfp + 3;
  3410. X    val = (*getsubr(fun))();
  3411. X    xlargc = oldargc;
  3412. X    xlargv = oldargv;
  3413. X    break;
  3414. X    case CONS:
  3415. X    if (!consp(cdr(fun)))
  3416. X        xlerror("bad function",fun);
  3417. X    if (car(fun) == s_lambda)
  3418. X        fun = xlclose(NIL,
  3419. X                      s_lambda,
  3420. X                      car(cdr(fun)),
  3421. X                      cdr(cdr(fun)),
  3422. X                      xlenv,xlfenv);
  3423. X    else
  3424. X        xlerror("bad function",fun);
  3425. X    /**** fall through into the next case ****/
  3426. X    case CLOSURE:
  3427. X    if (gettype(fun) != s_lambda)
  3428. X        xlerror("bad function",fun);
  3429. X    val = evfun(fun,argc,xlfp+3);
  3430. X    break;
  3431. X    default:
  3432. X    xlerror("bad function",fun);
  3433. X    }
  3434. X
  3435. X    /* remove the call frame */
  3436. X    xlsp = xlfp;
  3437. X    xlfp = xlfp - (int)getfixnum(*xlfp);
  3438. X
  3439. X    /* return the function value */
  3440. X    return (val);
  3441. X}
  3442. X
  3443. X/* evform - evaluate a form */
  3444. XLOCAL LVAL evform(form)
  3445. X  LVAL form;
  3446. X{
  3447. X    LVAL fun,args,val,type;
  3448. X    LVAL tracing=NIL;
  3449. X    LVAL *argv;
  3450. X    int argc;
  3451. X
  3452. X    /* protect some pointers */
  3453. X    xlstkcheck(2);
  3454. X    xlsave(fun);
  3455. X    xlsave(args);
  3456. X
  3457. X    /* get the function and the argument list */
  3458. X    fun = car(form);
  3459. X    args = cdr(form);
  3460. X
  3461. X    /* get the functional value of symbols */
  3462. X    if (symbolp(fun)) {
  3463. X    if (getvalue(s_tracelist) && member(fun,getvalue(s_tracelist)))
  3464. X        tracing = fun;
  3465. X    fun = xlgetfunction(fun);
  3466. X    }
  3467. X
  3468. X    /* check for nil */
  3469. X    if (null(fun))
  3470. X    xlerror("bad function",NIL);
  3471. X
  3472. X    /* dispatch on node type */
  3473. X    switch (ntype(fun)) {
  3474. X    case SUBR:
  3475. X    argv = xlargv;
  3476. X    argc = xlargc;
  3477. X    xlargc = evpushargs(fun,args);
  3478. X    xlargv = xlfp + 3;
  3479. X    trenter(tracing,xlargc,xlargv);
  3480. X    val = (*getsubr(fun))();
  3481. X    trexit(tracing,val);
  3482. X    xlsp = xlfp;
  3483. X    xlfp = xlfp - (int)getfixnum(*xlfp);
  3484. X    xlargv = argv;
  3485. X    xlargc = argc;
  3486. X    break;
  3487. X    case FSUBR:
  3488. X    argv = xlargv;
  3489. X    argc = xlargc;
  3490. X    xlargc = pushargs(fun,args);
  3491. X    xlargv = xlfp + 3;
  3492. X    val = (*getsubr(fun))();
  3493. X    xlsp = xlfp;
  3494. X    xlfp = xlfp - (int)getfixnum(*xlfp);
  3495. X    xlargv = argv;
  3496. X    xlargc = argc;
  3497. X    break;
  3498. X    case CONS:
  3499. X    if (!consp(cdr(fun)))
  3500. X        xlerror("bad function",fun);
  3501. X    if ((type = car(fun)) == s_lambda)
  3502. X         fun = xlclose(NIL,
  3503. X                       s_lambda,
  3504. X                       car(cdr(fun)),
  3505. X                       cdr(cdr(fun)),
  3506. X                       xlenv,xlfenv);
  3507. X    else
  3508. X        xlerror("bad function",fun);
  3509. X    /**** fall through into the next case ****/
  3510. X    case CLOSURE:
  3511. X    if (gettype(fun) == s_lambda) {
  3512. X        argc = evpushargs(fun,args);
  3513. X        argv = xlfp + 3;
  3514. X        trenter(tracing,argc,argv);
  3515. X        val = evfun(fun,argc,argv);
  3516. X        trexit(tracing,val);
  3517. X        xlsp = xlfp;
  3518. X        xlfp = xlfp - (int)getfixnum(*xlfp);
  3519. X    }
  3520. X    else {
  3521. X        macroexpand(fun,args,&fun);
  3522. X        val = xleval(fun);
  3523. X    }
  3524. X    break;
  3525. X    default:
  3526. X    xlerror("bad function",fun);
  3527. X    }
  3528. X
  3529. X    /* restore the stack */
  3530. X    xlpopn(2);
  3531. X
  3532. X    /* return the result value */
  3533. X    return (val);
  3534. X}
  3535. X
  3536. X/* xlexpandmacros - expand macros in a form */
  3537. XLVAL xlexpandmacros(form)
  3538. X  LVAL form;
  3539. X{
  3540. X    LVAL fun,args;
  3541. X    
  3542. X    /* protect some pointers */
  3543. X    xlstkcheck(3);
  3544. X    xlprotect(form);
  3545. X    xlsave(fun);
  3546. X    xlsave(args);
  3547. X
  3548. X    /* expand until the form isn't a macro call */
  3549. X    while (consp(form)) {
  3550. X    fun = car(form);        /* get the macro name */
  3551. X    args = cdr(form);        /* get the arguments */
  3552. X    if (!symbolp(fun) || !fboundp(fun))
  3553. X        break;
  3554. X    fun = xlgetfunction(fun);    /* get the expansion function */
  3555. X    if (!macroexpand(fun,args,&form))
  3556. X        break;
  3557. X    }
  3558. X
  3559. X    /* restore the stack and return the expansion */
  3560. X    xlpopn(3);
  3561. X    return (form);
  3562. X}
  3563. X
  3564. X/* macroexpand - expand a macro call */
  3565. Xint macroexpand(fun,args,pval)
  3566. X  LVAL fun,args,*pval;
  3567. X{
  3568. X    LVAL *argv;
  3569. X    int argc;
  3570. X    
  3571. X    /* make sure it's really a macro call */
  3572. X    if (!closurep(fun) || gettype(fun) != s_macro)
  3573. X    return (FALSE);
  3574. X    
  3575. X    /* call the expansion function */
  3576. X    argc = pushargs(fun,args);
  3577. X    argv = xlfp + 3;
  3578. X    *pval = evfun(fun,argc,argv);
  3579. X    xlsp = xlfp;
  3580. X    xlfp = xlfp - (int)getfixnum(*xlfp);
  3581. X    return (TRUE);
  3582. X}
  3583. X
  3584. X/* evalhook - call the evalhook function */
  3585. XLOCAL LVAL evalhook(expr)
  3586. X  LVAL expr;
  3587. X{
  3588. X    LVAL *newfp,olddenv,val;
  3589. X
  3590. X    /* create the new call frame */
  3591. X    newfp = xlsp;
  3592. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  3593. X    pusharg(getvalue(s_evalhook));
  3594. X    pusharg(cvfixnum((FIXTYPE)2));
  3595. X    pusharg(expr);
  3596. X    pusharg(cons(xlenv,xlfenv));
  3597. X    xlfp = newfp;
  3598. X
  3599. X    /* rebind the hook functions to nil */
  3600. X    olddenv = xldenv;
  3601. X    xldbind(s_evalhook,NIL);
  3602. X    xldbind(s_applyhook,NIL);
  3603. X
  3604. X    /* call the hook function */
  3605. X    val = xlapply(2);
  3606. X
  3607. X    /* unbind the symbols */
  3608. X    xlunbind(olddenv);
  3609. X
  3610. X    /* return the value */
  3611. X    return (val);
  3612. X}
  3613. X
  3614. X/* evpushargs - evaluate and push a list of arguments */
  3615. XLOCAL int evpushargs(fun,args)
  3616. X  LVAL fun,args;
  3617. X{
  3618. X    LVAL *newfp;
  3619. X    int argc;
  3620. X    
  3621. X    /* protect the argument list */
  3622. X    xlprot1(args);
  3623. X
  3624. X    /* build a new argument stack frame */
  3625. X    newfp = xlsp;
  3626. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  3627. X    pusharg(fun);
  3628. X    pusharg(NIL); /* will be argc */
  3629. X
  3630. X    /* evaluate and push each argument */
  3631. X    for (argc = 0; consp(args); args = cdr(args), ++argc)
  3632. X    pusharg(xleval(car(args)));
  3633. X
  3634. X    /* establish the new stack frame */
  3635. X    newfp[2] = cvfixnum((FIXTYPE)argc);
  3636. X    xlfp = newfp;
  3637. X    
  3638. X    /* restore the stack */
  3639. X    xlpop();
  3640. X
  3641. X    /* return the number of arguments */
  3642. X    return (argc);
  3643. X}
  3644. X
  3645. X/* pushargs - push a list of arguments */
  3646. Xint pushargs(fun,args)
  3647. X  LVAL fun,args;
  3648. X{
  3649. X    LVAL *newfp;
  3650. X    int argc;
  3651. X    
  3652. X    /* build a new argument stack frame */
  3653. X    newfp = xlsp;
  3654. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  3655. X    pusharg(fun);
  3656. X    pusharg(NIL); /* will be argc */
  3657. X
  3658. X    /* push each argument */
  3659. X    for (argc = 0; consp(args); args = cdr(args), ++argc)
  3660. X    pusharg(car(args));
  3661. X
  3662. X    /* establish the new stack frame */
  3663. X    newfp[2] = cvfixnum((FIXTYPE)argc);
  3664. X    xlfp = newfp;
  3665. X
  3666. X    /* return the number of arguments */
  3667. X    return (argc);
  3668. X}
  3669. X
  3670. X/* makearglist - make a list of the remaining arguments */
  3671. XLVAL makearglist(argc,argv)
  3672. X  int argc; LVAL *argv;
  3673. X{
  3674. X    LVAL list,this,last;
  3675. X    xlsave1(list);
  3676. X    for (last = NIL; --argc >= 0; last = this) {
  3677. X    this = cons(*argv++,NIL);
  3678. X    if (last) rplacd(last,this);
  3679. X    else list = this;
  3680. X    last = this;
  3681. X    }
  3682. X    xlpop();
  3683. X    return (list);
  3684. X}
  3685. X
  3686. X/* evfun - evaluate a function */
  3687. XLOCAL LVAL evfun(fun,argc,argv)
  3688. X  LVAL fun; int argc; LVAL *argv;
  3689. X{
  3690. X    LVAL oldenv,oldfenv,cptr,name,val;
  3691. X    CONTEXT cntxt;
  3692. X
  3693. X    /* protect some pointers */
  3694. X    xlstkcheck(3);
  3695. X    xlsave(oldenv);
  3696. X    xlsave(oldfenv);
  3697. X    xlsave(cptr);
  3698. X
  3699. X    /* create a new environment frame */
  3700. X    oldenv = xlenv;
  3701. X    oldfenv = xlfenv;
  3702. X    xlenv = xlframe(getenv(fun));
  3703. X    xlfenv = getfenv(fun);
  3704. X
  3705. X    /* bind the formal parameters */
  3706. X    xlabind(fun,argc,argv);
  3707. X
  3708. X    /* setup the implicit block */
  3709. X    if (name = getname(fun))
  3710. X    xlbegin(&cntxt,CF_RETURN,name);
  3711. X
  3712. X    /* execute the block */
  3713. X    if (name && setjmp(cntxt.c_jmpbuf))
  3714. X    val = xlvalue;
  3715. X    else
  3716. X    for (val = NIL, cptr = getbody(fun); consp(cptr); cptr = cdr(cptr))
  3717. X        val = xleval(car(cptr));
  3718. X
  3719. X    /* finish the block context */
  3720. X    if (name)
  3721. X    xlend(&cntxt);
  3722. X
  3723. X    /* restore the environment */
  3724. X    xlenv = oldenv;
  3725. X    xlfenv = oldfenv;
  3726. X
  3727. X    /* restore the stack */
  3728. X    xlpopn(3);
  3729. X
  3730. X    /* return the result value */
  3731. X    return (val);
  3732. X}
  3733. X
  3734. X/* xlclose - create a function closure */
  3735. XLVAL xlclose(name,type,fargs,body,env,fenv)
  3736. X  LVAL name,type,fargs,body,env,fenv;
  3737. X{
  3738. X    LVAL closure,key,arg,def,svar,new,last;
  3739. X    char keyname[STRMAX+2];
  3740. X
  3741. X    /* protect some pointers */
  3742. X    xlsave1(closure);
  3743. X
  3744. X    /* create the closure object */
  3745. X    closure = newclosure(name,type,env,fenv);
  3746. X    setlambda(closure,fargs);
  3747. X    setbody(closure,body);
  3748. X
  3749. X    /* handle each required argument */
  3750. X    last = NIL;
  3751. X    while (consp(fargs) && (arg = car(fargs)) && !iskey(arg)) {
  3752. X
  3753. X    /* make sure the argument is a symbol */
  3754. X    if (!symbolp(arg))
  3755. X        badarglist();
  3756. X
  3757. X    /* create a new argument list entry */
  3758. X    new = cons(arg,NIL);
  3759. X
  3760. X    /* link it into the required argument list */
  3761. X    if (last)
  3762. X        rplacd(last,new);
  3763. X    else
  3764. X        setargs(closure,new);
  3765. X    last = new;
  3766. X
  3767. X    /* move the formal argument list pointer ahead */
  3768. X    fargs = cdr(fargs);
  3769. X    }
  3770. X
  3771. X    /* check for the '&optional' keyword */
  3772. X    if (consp(fargs) && car(fargs) == lk_optional) {
  3773. X    fargs = cdr(fargs);
  3774. X
  3775. X    /* handle each optional argument */
  3776. X    last = NIL;
  3777. X    while (consp(fargs) && (arg = car(fargs)) && !iskey(arg)) {
  3778. X
  3779. X        /* get the default expression and specified-p variable */
  3780. X        def = svar = NIL;
  3781. X        if (consp(arg)) {
  3782. X        if (def = cdr(arg))
  3783. X            if (consp(def)) {
  3784. X            if (svar = cdr(def))
  3785. X                if (consp(svar)) {
  3786. X                svar = car(svar);
  3787. X                if (!symbolp(svar))
  3788. X                    badarglist();
  3789. X                }
  3790. X                else
  3791. X                badarglist();
  3792. X            def = car(def);
  3793. X            }
  3794. X            else
  3795. X            badarglist();
  3796. X        arg = car(arg);
  3797. X        }
  3798. X
  3799. X        /* make sure the argument is a symbol */
  3800. X        if (!symbolp(arg))
  3801. X        badarglist();
  3802. X
  3803. X        /* create a fully expanded optional expression */
  3804. X        new = cons(cons(arg,cons(def,cons(svar,NIL))),NIL);
  3805. X
  3806. X        /* link it into the optional argument list */
  3807. X        if (last)
  3808. X        rplacd(last,new);
  3809. X        else
  3810. X        setoargs(closure,new);
  3811. X        last = new;
  3812. X        
  3813. X        /* move the formal argument list pointer ahead */
  3814. X        fargs = cdr(fargs);
  3815. X    }
  3816. X    }
  3817. X
  3818. X    /* check for the '&rest' keyword */
  3819. X    if (consp(fargs) && car(fargs) == lk_rest) {
  3820. X    fargs = cdr(fargs);
  3821. X
  3822. X    /* get the &rest argument */
  3823. X    if (consp(fargs) && (arg = car(fargs)) && !iskey(arg) && symbolp(arg))
  3824. X        setrest(closure,arg);
  3825. X    else
  3826. X        badarglist();
  3827. X
  3828. X    /* move the formal argument list pointer ahead */
  3829. X    fargs = cdr(fargs);
  3830. X    }
  3831. X
  3832. X    /* check for the '&key' keyword */
  3833. X    if (consp(fargs) && car(fargs) == lk_key) {
  3834. X    fargs = cdr(fargs);
  3835. X
  3836. X     /* handle each key argument */
  3837. X    last = NIL;
  3838. X    while (consp(fargs) && (arg = car(fargs)) && !iskey(arg)) {
  3839. X
  3840. X        /* get the default expression and specified-p variable */
  3841. X        def = svar = NIL;
  3842. X        if (consp(arg)) {
  3843. X        if (def = cdr(arg))
  3844. X            if (consp(def)) {
  3845. X            if (svar = cdr(def))
  3846. X                if (consp(svar)) {
  3847. X                svar = car(svar);
  3848. X                if (!symbolp(svar))
  3849. X                    badarglist();
  3850. X                }
  3851. X                else
  3852. X                badarglist();
  3853. X            def = car(def);
  3854. X            }
  3855. X            else
  3856. X            badarglist();
  3857. X        arg = car(arg);
  3858. X        }
  3859. X
  3860. X        /* get the keyword and the variable */
  3861. X        if (consp(arg)) {
  3862. X        key = car(arg);
  3863. X        if (!symbolp(key))
  3864. X            badarglist();
  3865. X        if (arg = cdr(arg))
  3866. X            if (consp(arg))
  3867. X            arg = car(arg);
  3868. X            else
  3869. X            badarglist();
  3870. X        }
  3871. X        else if (symbolp(arg)) {
  3872. X        strcpy(keyname,":");
  3873. X        strcat(keyname,getstring(getpname(arg)));
  3874. X        key = xlenter(keyname);
  3875. X        }
  3876. X
  3877. X        /* make sure the argument is a symbol */
  3878. X        if (!symbolp(arg))
  3879. X        badarglist();
  3880. X
  3881. X        /* create a fully expanded key expression */
  3882. X        new = cons(cons(key,cons(arg,cons(def,cons(svar,NIL)))),NIL);
  3883. X
  3884. X        /* link it into the optional argument list */
  3885. X        if (last)
  3886. X        rplacd(last,new);
  3887. X        else
  3888. X        setkargs(closure,new);
  3889. X        last = new;
  3890. X
  3891. X        /* move the formal argument list pointer ahead */
  3892. X        fargs = cdr(fargs);
  3893. X    }
  3894. X    }
  3895. X
  3896. X    /* check for the '&allow-other-keys' keyword */
  3897. X    if (consp(fargs) && car(fargs) == lk_allow_other_keys)
  3898. X    fargs = cdr(fargs);    /* this is the default anyway */
  3899. X
  3900. X    /* check for the '&aux' keyword */
  3901. X    if (consp(fargs) && car(fargs) == lk_aux) {
  3902. X    fargs = cdr(fargs);
  3903. X
  3904. X    /* handle each aux argument */
  3905. X    last = NIL;
  3906. X    while (consp(fargs) && (arg = car(fargs)) && !iskey(arg)) {
  3907. X
  3908. X        /* get the initial value */
  3909. X        def = NIL;
  3910. X        if (consp(arg)) {
  3911. X        if (def = cdr(arg))
  3912. X            if (consp(def))
  3913. X            def = car(def);
  3914. X            else
  3915. X            badarglist();
  3916. X        arg = car(arg);
  3917. X        }
  3918. X
  3919. X        /* make sure the argument is a symbol */
  3920. X        if (!symbolp(arg))
  3921. X        badarglist();
  3922. X
  3923. X        /* create a fully expanded aux expression */
  3924. X        new = cons(cons(arg,cons(def,NIL)),NIL);
  3925. X
  3926. X        /* link it into the aux argument list */
  3927. X        if (last)
  3928. X        rplacd(last,new);
  3929. X        else
  3930. X        setaargs(closure,new);
  3931. X        last = new;
  3932. X
  3933. X        /* move the formal argument list pointer ahead */
  3934. X        fargs = cdr(fargs);
  3935. X    }
  3936. X    }
  3937. X
  3938. X    /* make sure this is the end of the formal argument list */
  3939. X    if (fargs)
  3940. X    badarglist();
  3941. X
  3942. X    /* restore the stack */
  3943. X    xlpop();
  3944. X
  3945. X    /* return the new closure */
  3946. X    return (closure);
  3947. X}
  3948. X
  3949. X/* xlabind - bind the arguments for a function */
  3950. Xxlabind(fun,argc,argv)
  3951. X  LVAL fun; int argc; LVAL *argv;
  3952. X{
  3953. X    LVAL *kargv,fargs,key,arg,def,svar,p;
  3954. X    int rargc,kargc;
  3955. X    
  3956. X    /* protect some pointers */
  3957. X    xlsave1(def);
  3958. X
  3959. X    /* bind each required argument */
  3960. X    for (fargs = getargs(fun); fargs; fargs = cdr(fargs)) {
  3961. X
  3962. X    /* make sure there is an actual argument */
  3963. X    if (--argc < 0)
  3964. X        xlfail("too few arguments");
  3965. X
  3966. X    /* bind the formal variable to the argument value */
  3967. X    xlbind(car(fargs),*argv++);
  3968. X    }
  3969. X
  3970. X    /* bind each optional argument */
  3971. X    for (fargs = getoargs(fun); fargs; fargs = cdr(fargs)) {
  3972. X
  3973. X    /* get argument, default and specified-p variable */
  3974. X    p = car(fargs);
  3975. X    arg = car(p); p = cdr(p);
  3976. X    def = car(p); p = cdr(p);
  3977. X    svar = car(p);
  3978. X
  3979. X    /* bind the formal variable to the argument value */
  3980. X    if (--argc >= 0) {
  3981. X        xlbind(arg,*argv++);
  3982. X        if (svar) xlbind(svar,true);
  3983. X    }
  3984. X
  3985. X    /* bind the formal variable to the default value */
  3986. X    else {
  3987. X        if (def) def = xleval(def);
  3988. X        xlbind(arg,def);
  3989. X        if (svar) xlbind(svar,NIL);
  3990. X    }
  3991. X    }
  3992. X
  3993. X    /* save the count of the &rest of the argument list */
  3994. X    rargc = argc;
  3995. X    
  3996. X    /* handle '&rest' argument */
  3997. X    if (arg = getrest(fun)) {
  3998. X    def = makearglist(argc,argv);
  3999. X    xlbind(arg,def);
  4000. X    argc = 0;
  4001. X    }
  4002. X
  4003. X    /* handle '&key' arguments */
  4004. X    if (fargs = getkargs(fun)) {
  4005. X    for (; fargs; fargs = cdr(fargs)) {
  4006. X
  4007. X        /* get keyword, argument, default and specified-p variable */
  4008. X        p = car(fargs);
  4009. X        key = car(p); p = cdr(p);
  4010. X        arg = car(p); p = cdr(p);
  4011. X        def = car(p); p = cdr(p);
  4012. X        svar = car(p);
  4013. X
  4014. X        /* look for the keyword in the actual argument list */
  4015. X        for (kargv = argv, kargc = rargc; (kargc -= 2) >= 0; kargv += 2)
  4016. X        if (*kargv == key)
  4017. X            break;
  4018. X
  4019. X        /* bind the formal variable to the argument value */
  4020. X        if (kargc >= 0) {
  4021. X        xlbind(arg,*++kargv);
  4022. X        if (svar) xlbind(svar,true);
  4023. X        }
  4024. X
  4025. X        /* bind the formal variable to the default value */
  4026. X        else {
  4027. X        if (def) def = xleval(def);
  4028. X        xlbind(arg,def);
  4029. X        if (svar) xlbind(svar,NIL);
  4030. X        }
  4031. X    }
  4032. X    argc = 0;
  4033. X    }
  4034. X
  4035. X    /* check for the '&aux' keyword */
  4036. X    for (fargs = getaargs(fun); fargs; fargs = cdr(fargs)) {
  4037. X
  4038. X    /* get argument and default */
  4039. X    p = car(fargs);
  4040. X    arg = car(p); p = cdr(p);
  4041. X    def = car(p);
  4042. X
  4043. X    /* bind the auxiliary variable to the initial value */
  4044. X    if (def) def = xleval(def);
  4045. X    xlbind(arg,def);
  4046. X    }
  4047. X
  4048. X    /* make sure there aren't too many arguments */
  4049. X    if (argc > 0)
  4050. X    xlfail("too many arguments");
  4051. X
  4052. X    /* restore the stack */
  4053. X    xlpop();
  4054. X}
  4055. X
  4056. X/* doenter - print trace information on function entry */
  4057. XLOCAL doenter(sym,argc,argv)
  4058. X  LVAL sym; int argc; LVAL *argv;
  4059. X{
  4060. X    extern int xltrcindent;
  4061. X    int i;
  4062. X    
  4063. X    /* indent to the current trace level */
  4064. X    for (i = 0; i < xltrcindent; ++i)
  4065. X    trcputstr(" ");
  4066. X    ++xltrcindent;
  4067. X
  4068. X    /* display the function call */
  4069. X    sprintf(buf,"Entering: %s, Argument list: (",getstring(getpname(sym)));
  4070. X    trcputstr(buf);
  4071. X    while (--argc >= 0) {
  4072. X    trcprin1(*argv++);
  4073. X    if (argc) trcputstr(" ");
  4074. X    }
  4075. X    trcputstr(")\n");
  4076. X}
  4077. X
  4078. X/* doexit - print trace information for function/macro exit */
  4079. XLOCAL doexit(sym,val)
  4080. X  LVAL sym,val;
  4081. X{
  4082. X    extern int xltrcindent;
  4083. X    int i;
  4084. X    
  4085. X    /* indent to the current trace level */
  4086. X    --xltrcindent;
  4087. X    for (i = 0; i < xltrcindent; ++i)
  4088. X    trcputstr(" ");
  4089. X    
  4090. X    /* display the function value */
  4091. X    sprintf(buf,"Exiting: %s, Value: ",getstring(getpname(sym)));
  4092. X    trcputstr(buf);
  4093. X    trcprin1(val);
  4094. X    trcputstr("\n");
  4095. X}
  4096. X
  4097. X/* member - is 'x' a member of 'list'? */
  4098. XLOCAL int member(x,list)
  4099. X  LVAL x,list;
  4100. X{
  4101. X    for (; consp(list); list = cdr(list))
  4102. X    if (x == car(list))
  4103. X        return (TRUE);
  4104. X    return (FALSE);
  4105. X}
  4106. X
  4107. X/* xlunbound - signal an unbound variable error */
  4108. Xxlunbound(sym)
  4109. X  LVAL sym;
  4110. X{
  4111. X    xlcerror("try evaluating symbol again","unbound variable",sym);
  4112. X}
  4113. X
  4114. X/* xlfunbound - signal an unbound function error */
  4115. Xxlfunbound(sym)
  4116. X  LVAL sym;
  4117. X{
  4118. X    xlcerror("try evaluating symbol again","unbound function",sym);
  4119. X}
  4120. X
  4121. X/* xlstkoverflow - signal a stack overflow error */
  4122. Xxlstkoverflow()
  4123. X{
  4124. X    xlabort("evaluation stack overflow");
  4125. X}
  4126. X
  4127. X/* xlargstkoverflow - signal an argument stack overflow error */
  4128. Xxlargstkoverflow()
  4129. X{
  4130. X    xlabort("argument stack overflow");
  4131. X}
  4132. X
  4133. X/* badarglist - report a bad argument list error */
  4134. XLOCAL badarglist()
  4135. X{
  4136. X    xlfail("bad formal argument list");
  4137. X}
  4138. SHAR_EOF
  4139. if test 19240 -ne "`wc -c 'xleval.c'`"
  4140. then
  4141.     echo shar: error transmitting "'xleval.c'" '(should have been 19240 characters)'
  4142. fi
  4143. #    End of shell archive
  4144. exit 0
  4145. -- 
  4146. Gary Murphy                   uunet!mitel!sce!cognos!garym
  4147.                               (garym%cognos.uucp@uunet.uu.net)
  4148. (613) 738-1338 x5537          Cognos Inc. P.O. Box 9707 Ottawa K1G 3N3
  4149. "There are many things which do not concern the process" - Joan of Arc
  4150.  
  4151.